• 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
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktMeshShaderMiscTests.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkBuilderUtil.hpp"
29 #include "vkImageWithMemory.hpp"
30 #include "vkBufferWithMemory.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 
37 #include "tcuImageCompare.hpp"
38 #include "tcuTexture.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuMaybe.hpp"
41 #include "tcuStringTemplate.hpp"
42 #include "tcuTestLog.hpp"
43 
44 #include <memory>
45 #include <utility>
46 #include <vector>
47 #include <string>
48 #include <sstream>
49 #include <map>
50 
51 namespace vkt
52 {
53 namespace MeshShader
54 {
55 
56 namespace
57 {
58 
59 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
60 
61 using namespace vk;
62 
63 // Output images will use this format.
getOutputFormat()64 VkFormat getOutputFormat ()
65 {
66 	return VK_FORMAT_R8G8B8A8_UNORM;
67 }
68 
69 // Threshold that's reasonable for the previous format.
getCompareThreshold()70 float getCompareThreshold ()
71 {
72 	return 0.005f; // 1/256 < 0.005 < 2/256
73 }
74 
75 // Check mesh shader support.
genericCheckSupport(Context & context,bool requireTaskShader,bool requireVertexStores)76 void genericCheckSupport (Context& context, bool requireTaskShader, bool requireVertexStores)
77 {
78 	context.requireDeviceFunctionality("VK_NV_mesh_shader");
79 
80 	const auto& meshFeatures = context.getMeshShaderFeatures();
81 
82 	if (!meshFeatures.meshShader)
83 		TCU_THROW(NotSupportedError, "Mesh shader not supported");
84 
85 	if (requireTaskShader && !meshFeatures.taskShader)
86 		TCU_THROW(NotSupportedError, "Task shader not supported");
87 
88 	if (requireVertexStores)
89 	{
90 		const auto& features = context.getDeviceFeatures();
91 		if (!features.vertexPipelineStoresAndAtomics)
92 			TCU_THROW(NotSupportedError, "Vertex pieline stores and atomics not supported");
93 	}
94 }
95 
96 struct MiscTestParams
97 {
98 	tcu::Maybe<uint32_t>	taskCount;
99 	uint32_t				meshCount;
100 
101 	uint32_t				width;
102 	uint32_t				height;
103 
104 	// Makes the class polymorphic and allows the right destructor to be used for subclasses.
~MiscTestParamsvkt::MeshShader::__anona67b1ba90111::MiscTestParams105 	virtual ~MiscTestParams () {}
106 
needsTaskShadervkt::MeshShader::__anona67b1ba90111::MiscTestParams107 	bool needsTaskShader () const
108 	{
109 		return static_cast<bool>(taskCount);
110 	}
111 
drawCountvkt::MeshShader::__anona67b1ba90111::MiscTestParams112 	uint32_t drawCount () const
113 	{
114 		if (needsTaskShader())
115 			return taskCount.get();
116 		return meshCount;
117 	}
118 };
119 
120 using ParamsPtr = std::unique_ptr<MiscTestParams>;
121 
122 class MeshShaderMiscCase : public vkt::TestCase
123 {
124 public:
125 					MeshShaderMiscCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params);
~MeshShaderMiscCase(void)126 	virtual			~MeshShaderMiscCase		(void) {}
127 
128 	void			checkSupport			(Context& context) const override;
129 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
130 
131 protected:
132 	std::unique_ptr<MiscTestParams> m_params;
133 };
134 
MeshShaderMiscCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)135 MeshShaderMiscCase::MeshShaderMiscCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
136 	: vkt::TestCase	(testCtx, name, description)
137 	, m_params		(params.release())
138 {}
139 
checkSupport(Context & context) const140 void MeshShaderMiscCase::checkSupport (Context& context) const
141 {
142 	genericCheckSupport(context, m_params->needsTaskShader(), /*requireVertexStores*/false);
143 }
144 
145 // Adds the generic fragment shader. To be called by subclasses.
initPrograms(vk::SourceCollections & programCollection) const146 void MeshShaderMiscCase::initPrograms (vk::SourceCollections& programCollection) const
147 {
148 	std::string frag =
149 		"#version 450\n"
150 		"#extension GL_NV_mesh_shader : enable\n"
151 		"\n"
152 		"layout (location=0) in perprimitiveNV vec4 primitiveColor;\n"
153 		"layout (location=0) out vec4 outColor;\n"
154 		"\n"
155 		"void main ()\n"
156 		"{\n"
157 		"    outColor = primitiveColor;\n"
158 		"}\n"
159 		;
160 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
161 }
162 
163 class MeshShaderMiscInstance : public vkt::TestInstance
164 {
165 public:
MeshShaderMiscInstance(Context & context,const MiscTestParams * params)166 					MeshShaderMiscInstance	(Context& context, const MiscTestParams* params)
167 						: vkt::TestInstance	(context)
168 						, m_params			(params)
169 						, m_referenceLevel	()
170 					{
171 					}
172 
173 	void			generateSolidRefLevel	(const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output);
174 	virtual void	generateReferenceLevel	() = 0;
175 
176 	virtual bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const;
177 	virtual bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess) const;
178 	tcu::TestStatus	iterate					() override;
179 
180 protected:
181 	const MiscTestParams*				m_params;
182 	std::unique_ptr<tcu::TextureLevel>	m_referenceLevel;
183 };
184 
generateSolidRefLevel(const tcu::Vec4 & color,std::unique_ptr<tcu::TextureLevel> & output)185 void MeshShaderMiscInstance::generateSolidRefLevel (const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output)
186 {
187 	const auto format		= getOutputFormat();
188 	const auto tcuFormat	= mapVkFormat(format);
189 
190 	const auto iWidth		= static_cast<int>(m_params->width);
191 	const auto iHeight		= static_cast<int>(m_params->height);
192 
193 	output.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
194 
195 	const auto access		= output->getAccess();
196 
197 	// Fill with solid color.
198 	tcu::clear(access, color);
199 }
200 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess) const201 bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
202 {
203 	return verifyResult(resultAccess, *m_referenceLevel);
204 }
205 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess,const tcu::TextureLevel & referenceLevel) const206 bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const
207 {
208 	const auto referenceAccess = referenceLevel.getAccess();
209 
210 	const auto refWidth		= referenceAccess.getWidth();
211 	const auto refHeight	= referenceAccess.getHeight();
212 	const auto refDepth		= referenceAccess.getDepth();
213 
214 	const auto resWidth		= resultAccess.getWidth();
215 	const auto resHeight	= resultAccess.getHeight();
216 	const auto resDepth		= resultAccess.getDepth();
217 
218 	DE_ASSERT(resWidth == refWidth || resHeight == refHeight || resDepth == refDepth);
219 
220 	// For release builds.
221 	DE_UNREF(refWidth);
222 	DE_UNREF(refHeight);
223 	DE_UNREF(refDepth);
224 	DE_UNREF(resWidth);
225 	DE_UNREF(resHeight);
226 	DE_UNREF(resDepth);
227 
228 	const auto outputFormat		= getOutputFormat();
229 	const auto expectedFormat	= mapVkFormat(outputFormat);
230 	const auto resFormat		= resultAccess.getFormat();
231 	const auto refFormat		= referenceAccess.getFormat();
232 
233 	DE_ASSERT(resFormat == expectedFormat && refFormat == expectedFormat);
234 
235 	// For release builds
236 	DE_UNREF(expectedFormat);
237 	DE_UNREF(resFormat);
238 	DE_UNREF(refFormat);
239 
240 	auto&			log				= m_context.getTestContext().getLog();
241 	const auto		threshold		= getCompareThreshold();
242 	const tcu::Vec4	thresholdVec	(threshold, threshold, threshold, threshold);
243 
244 	return tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, thresholdVec, tcu::COMPARE_LOG_ON_ERROR);
245 }
246 
iterate()247 tcu::TestStatus MeshShaderMiscInstance::iterate ()
248 {
249 	const auto&		vkd			= m_context.getDeviceInterface();
250 	const auto		device		= m_context.getDevice();
251 	auto&			alloc		= m_context.getDefaultAllocator();
252 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
253 	const auto		queue		= m_context.getUniversalQueue();
254 
255 	const auto		imageFormat	= getOutputFormat();
256 	const auto		tcuFormat	= mapVkFormat(imageFormat);
257 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
258 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
259 
260 	const VkImageCreateInfo colorBufferInfo =
261 	{
262 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
263 		nullptr,								//	const void*				pNext;
264 		0u,										//	VkImageCreateFlags		flags;
265 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
266 		imageFormat,							//	VkFormat				format;
267 		imageExtent,							//	VkExtent3D				extent;
268 		1u,										//	uint32_t				mipLevels;
269 		1u,										//	uint32_t				arrayLayers;
270 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
271 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
272 		imageUsage,								//	VkImageUsageFlags		usage;
273 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
274 		0u,										//	uint32_t				queueFamilyIndexCount;
275 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
276 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
277 	};
278 
279 	// Create color image and view.
280 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
281 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
282 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
283 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
284 
285 	// Create a memory buffer for verification.
286 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
287 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
288 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
289 
290 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
291 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
292 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
293 
294 	// Pipeline layout.
295 	const auto pipelineLayout = makePipelineLayout(vkd, device);
296 
297 	// Shader modules.
298 	const auto&	binaries	= m_context.getBinaryCollection();
299 	const auto	hasTask		= binaries.contains("task");
300 
301 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
302 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
303 
304 	Move<VkShaderModule> taskShader;
305 	if (hasTask)
306 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
307 
308 	// Render pass.
309 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
310 
311 	// Framebuffer.
312 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
313 
314 	// Viewport and scissor.
315 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
316 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
317 
318 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
319 		taskShader.get(), meshShader.get(), fragShader.get(),
320 		renderPass.get(), viewports, scissors);
321 
322 	// Command pool and buffer.
323 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
324 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
325 	const auto cmdBuffer	= cmdBufferPtr.get();
326 
327 	beginCommandBuffer(vkd, cmdBuffer);
328 
329 	// Run pipeline.
330 	const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
331 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
332 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
333 	vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
334 	endRenderPass(vkd, cmdBuffer);
335 
336 	// Copy color buffer to verification buffer.
337 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
338 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
339 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
340 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
341 
342 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
343 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
344 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
345 
346 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
347 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
348 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
349 
350 	endCommandBuffer(vkd, cmdBuffer);
351 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
352 
353 	// Generate reference image and compare results.
354 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
355 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
356 
357 	generateReferenceLevel();
358 	invalidateAlloc(vkd, device, verificationBufferAlloc);
359 	if (!verifyResult(verificationAccess))
360 		TCU_FAIL("Result does not match reference; check log for details");
361 
362 	return tcu::TestStatus::pass("Pass");
363 }
364 
365 // Verify passing more complex data between the task and mesh shaders.
366 class ComplexTaskDataCase : public MeshShaderMiscCase
367 {
368 public:
ComplexTaskDataCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)369 					ComplexTaskDataCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
370 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
371 					{}
372 
373 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
374 	TestInstance*	createInstance			(Context& context) const override;
375 };
376 
377 class ComplexTaskDataInstance : public MeshShaderMiscInstance
378 {
379 public:
ComplexTaskDataInstance(Context & context,const MiscTestParams * params)380 	ComplexTaskDataInstance (Context& context, const MiscTestParams* params)
381 		: MeshShaderMiscInstance (context, params)
382 	{}
383 
384 	void	generateReferenceLevel	() override;
385 };
386 
generateReferenceLevel()387 void ComplexTaskDataInstance::generateReferenceLevel ()
388 {
389 	const auto format		= getOutputFormat();
390 	const auto tcuFormat	= mapVkFormat(format);
391 
392 	const auto iWidth		= static_cast<int>(m_params->width);
393 	const auto iHeight		= static_cast<int>(m_params->height);
394 
395 	const auto halfWidth	= iWidth / 2;
396 	const auto halfHeight	= iHeight / 2;
397 
398 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
399 
400 	const auto access		= m_referenceLevel->getAccess();
401 
402 	// Each image quadrant gets a different color.
403 	for (int y = 0; y < iHeight; ++y)
404 	for (int x = 0; x < iWidth; ++x)
405 	{
406 		const float	red			= ((y < halfHeight) ? 0.0f : 1.0f);
407 		const float	green		= ((x < halfWidth)  ? 0.0f : 1.0f);
408 		const auto	refColor	= tcu::Vec4(red, green, 1.0f, 1.0f);
409 		access.setPixel(refColor, x, y);
410 	}
411 }
412 
initPrograms(vk::SourceCollections & programCollection) const413 void ComplexTaskDataCase::initPrograms (vk::SourceCollections& programCollection) const
414 {
415 	// Add the generic fragment shader.
416 	MeshShaderMiscCase::initPrograms(programCollection);
417 
418 	const std::string taskDataDeclTemplate =
419 		"struct RowId {\n"
420 		"    uint id;\n"
421 		"};\n"
422 		"\n"
423 		"struct WorkGroupData {\n"
424 		"    float WorkGroupIdPlusOnex1000Iota[10];\n"
425 		"    RowId rowId;\n"
426 		"    uvec3 WorkGroupIdPlusOnex2000Iota;\n"
427 		"    vec2  WorkGroupIdPlusOnex3000Iota;\n"
428 		"};\n"
429 		"\n"
430 		"struct ExternalData {\n"
431 		"    float OneMillion;\n"
432 		"    uint  TwoMillion;\n"
433 		"    WorkGroupData workGroupData;\n"
434 		"};\n"
435 		"\n"
436 		"${INOUT} taskNV TaskData {\n"
437 		"    uint yes;\n"
438 		"    ExternalData externalData;\n"
439 		"} td;\n"
440 		;
441 	const tcu::StringTemplate taskDataDecl(taskDataDeclTemplate);
442 
443 	{
444 		std::map<std::string, std::string> taskMap;
445 		taskMap["INOUT"] = "out";
446 		std::ostringstream task;
447 		task
448 			<< "#version 450\n"
449 			<< "#extension GL_NV_mesh_shader : enable\n"
450 			<< "\n"
451 			<< "layout (local_size_x=1) in;\n"
452 			<< "\n"
453 			<< taskDataDecl.specialize(taskMap)
454 			<< "\n"
455 			<< "void main ()\n"
456 			<< "{\n"
457 			<< "    gl_TaskCountNV = 2u;\n"
458 			<< "    td.yes = 1u;\n"
459 			<< "    td.externalData.OneMillion = 1000000.0;\n"
460 			<< "    td.externalData.TwoMillion = 2000000u;\n"
461 			<< "    for (uint i = 0; i < 10; i++) {\n"
462 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] = float((gl_WorkGroupID.x + 1u) * 1000 + i);\n"
463 			<< "    }\n"
464 			<< "    {\n"
465 			<< "        uint baseVal = (gl_WorkGroupID.x + 1u) * 2000;\n"
466 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
467 			<< "    }\n"
468 			<< "    {\n"
469 			<< "        uint baseVal = (gl_WorkGroupID.x + 1u) * 3000;\n"
470 			<< "        td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota = vec2(baseVal, baseVal + 1);\n"
471 			<< "    }\n"
472 			<< "    td.externalData.workGroupData.rowId.id = gl_WorkGroupID.x;\n"
473 			<< "}\n"
474 			;
475 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
476 	}
477 
478 	{
479 		std::map<std::string, std::string> meshMap;
480 		meshMap["INOUT"] = "in";
481 		std::ostringstream mesh;
482 		mesh
483 			<< "#version 450\n"
484 			<< "#extension GL_NV_mesh_shader : enable\n"
485 			<< "\n"
486 			<< "layout(local_size_x=2) in;\n"
487 			<< "layout(triangles) out;\n"
488 			<< "layout(max_vertices=4, max_primitives=2) out;\n"
489 			<< "\n"
490 			<< "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
491 			<< "\n"
492 			<< taskDataDecl.specialize(meshMap)
493 			<< "\n"
494 			<< "void main ()\n"
495 			<< "{\n"
496 			<< "    bool dataOK = true;\n"
497 			<< "    dataOK = (dataOK && (td.yes == 1u));\n"
498 			<< "    dataOK = (dataOK && (td.externalData.OneMillion == 1000000.0 && td.externalData.TwoMillion == 2000000u));\n"
499 			<< "    uint rowId = td.externalData.workGroupData.rowId.id;\n"
500 			<< "    dataOK = (dataOK && (rowId == 0u || rowId == 1u));\n"
501 			<< "\n"
502 			<< "    {\n"
503 			<< "        uint baseVal = (rowId + 1u) * 1000u;\n"
504 			<< "        for (uint i = 0; i < 10; i++) {\n"
505 			<< "            if (td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] != float(baseVal + i)) {\n"
506 			<< "                dataOK = false;\n"
507 			<< "                break;\n"
508 			<< "            }\n"
509 			<< "        }\n"
510 			<< "    }\n"
511 			<< "\n"
512 			<< "    {\n"
513 			<< "        uint baseVal = (rowId + 1u) * 2000;\n"
514 			<< "        uvec3 expected = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
515 			<< "        if (td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota != expected) {\n"
516 			<< "            dataOK = false;\n"
517 			<< "        }\n"
518 			<< "    }\n"
519 			<< "\n"
520 			<< "    {\n"
521 			<< "        uint baseVal = (rowId + 1u) * 3000;\n"
522 			<< "        vec2 expected = vec2(baseVal, baseVal + 1);\n"
523 			<< "        if (td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota != expected) {\n"
524 			<< "            dataOK = false;\n"
525 			<< "        }\n"
526 			<< "    }\n"
527 			<< "\n"
528 			<< "    uint columnId = gl_WorkGroupID.x;\n"
529 			<< "\n"
530 			<< "    if (dataOK) {\n"
531 			<< "        gl_PrimitiveCountNV = 2u;\n"
532 			<< "    }\n"
533 			<< "    else {\n"
534 			<< "        gl_PrimitiveCountNV = 0u;\n"
535 			<< "        return;\n"
536 			<< "    }\n"
537 			<< "\n"
538 			<< "    const vec4 outColor = vec4(rowId, columnId, 1.0f, 1.0f);\n"
539 			<< "    triangleColor[0] = outColor;\n"
540 			<< "    triangleColor[1] = outColor;\n"
541 			<< "\n"
542 			<< "    // Each local invocation will generate two points and one triangle from the quad.\n"
543 			<< "    // The first local invocation will generate the top quad vertices.\n"
544 			<< "    // The second invocation will generate the two bottom vertices.\n"
545 			<< "    vec4 left  = vec4(0.0, 0.0, 0.0, 1.0);\n"
546 			<< "    vec4 right = vec4(1.0, 0.0, 0.0, 1.0);\n"
547 			<< "\n"
548 			<< "    float localInvocationOffsetY = float(gl_LocalInvocationID.x);\n"
549 			<< "    left.y  += localInvocationOffsetY;\n"
550 			<< "    right.y += localInvocationOffsetY;\n"
551 			<< "\n"
552 			<< "    // The code above creates a quad from (0, 0) to (1, 1) but we need to offset it\n"
553 			<< "    // in X and/or Y depending on the row and column, to place it in other quadrants.\n"
554 			<< "    float quadrantOffsetX = float(int(columnId) - 1);\n"
555 			<< "    float quadrantOffsetY = float(int(rowId) - 1);\n"
556 			<< "\n"
557 			<< "    left.x  += quadrantOffsetX;\n"
558 			<< "    right.x += quadrantOffsetX;\n"
559 			<< "\n"
560 			<< "    left.y  += quadrantOffsetY;\n"
561 			<< "    right.y += quadrantOffsetY;\n"
562 			<< "\n"
563 			<< "    uint baseVertexId = 2*gl_LocalInvocationID.x;\n"
564 			<< "    gl_MeshVerticesNV[baseVertexId + 0].gl_Position = left;\n"
565 			<< "    gl_MeshVerticesNV[baseVertexId + 1].gl_Position = right;\n"
566 			<< "\n"
567 			<< "    uint baseIndexId = 3*gl_LocalInvocationID.x;\n"
568 			<< "    // 0,1,2 or 1,2,3 (note: triangles alternate front face this way)\n"
569 			<< "    gl_PrimitiveIndicesNV[baseIndexId + 0] = 0 + gl_LocalInvocationID.x;\n"
570 			<< "    gl_PrimitiveIndicesNV[baseIndexId + 1] = 1 + gl_LocalInvocationID.x;\n"
571 			<< "    gl_PrimitiveIndicesNV[baseIndexId + 2] = 2 + gl_LocalInvocationID.x;\n"
572 			<< "}\n"
573 			;
574 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
575 	}
576 }
577 
createInstance(Context & context) const578 TestInstance* ComplexTaskDataCase::createInstance (Context& context) const
579 {
580 	return new ComplexTaskDataInstance(context, m_params.get());
581 }
582 
583 // Verify drawing a single point.
584 class SinglePointCase : public MeshShaderMiscCase
585 {
586 public:
SinglePointCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)587 					SinglePointCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
588 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
589 					{}
590 
591 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
592 	TestInstance*	createInstance			(Context& context) const override;
593 };
594 
595 class SinglePointInstance : public MeshShaderMiscInstance
596 {
597 public:
SinglePointInstance(Context & context,const MiscTestParams * params)598 	SinglePointInstance (Context& context, const MiscTestParams* params)
599 		: MeshShaderMiscInstance (context, params)
600 	{}
601 
602 	void	generateReferenceLevel	() override;
603 };
604 
createInstance(Context & context) const605 TestInstance* SinglePointCase::createInstance (Context& context) const
606 {
607 	return new SinglePointInstance (context, m_params.get());
608 }
609 
initPrograms(vk::SourceCollections & programCollection) const610 void SinglePointCase::initPrograms (vk::SourceCollections& programCollection) const
611 {
612 	DE_ASSERT(!m_params->needsTaskShader());
613 
614 	MeshShaderMiscCase::initPrograms(programCollection);
615 
616 	std::ostringstream mesh;
617 	mesh
618 		<< "#version 450\n"
619 		<< "#extension GL_NV_mesh_shader : enable\n"
620 		<< "\n"
621 		<< "layout(local_size_x=1) in;\n"
622 		<< "layout(points) out;\n"
623 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
624 		<< "\n"
625 		<< "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
626 		<< "\n"
627 		<< "void main ()\n"
628 		<< "{\n"
629 		<< "    gl_PrimitiveCountNV = 1u;\n"
630 		<< "    pointColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
631 		<< "    gl_MeshVerticesNV[0].gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
632 		<< "    gl_MeshVerticesNV[0].gl_PointSize = 1.0f;\n"
633 		<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
634 		<< "}\n"
635 		;
636 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
637 }
638 
generateReferenceLevel()639 void SinglePointInstance::generateReferenceLevel ()
640 {
641 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
642 
643 	const auto halfWidth	= static_cast<int>(m_params->width / 2u);
644 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
645 	const auto access		= m_referenceLevel->getAccess();
646 
647 	access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
648 }
649 
650 // Verify drawing a single line.
651 class SingleLineCase : public MeshShaderMiscCase
652 {
653 public:
SingleLineCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)654 					SingleLineCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
655 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
656 					{}
657 
658 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
659 	TestInstance*	createInstance			(Context& context) const override;
660 };
661 
662 class SingleLineInstance : public MeshShaderMiscInstance
663 {
664 public:
SingleLineInstance(Context & context,const MiscTestParams * params)665 	SingleLineInstance (Context& context, const MiscTestParams* params)
666 		: MeshShaderMiscInstance (context, params)
667 	{}
668 
669 	void	generateReferenceLevel	() override;
670 };
671 
createInstance(Context & context) const672 TestInstance* SingleLineCase::createInstance (Context& context) const
673 {
674 	return new SingleLineInstance (context, m_params.get());
675 }
676 
initPrograms(vk::SourceCollections & programCollection) const677 void SingleLineCase::initPrograms (vk::SourceCollections& programCollection) const
678 {
679 	DE_ASSERT(!m_params->needsTaskShader());
680 
681 	MeshShaderMiscCase::initPrograms(programCollection);
682 
683 	std::ostringstream mesh;
684 	mesh
685 		<< "#version 450\n"
686 		<< "#extension GL_NV_mesh_shader : enable\n"
687 		<< "\n"
688 		<< "layout(local_size_x=1) in;\n"
689 		<< "layout(lines) out;\n"
690 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
691 		<< "\n"
692 		<< "layout (location=0) out perprimitiveNV vec4 lineColor[];\n"
693 		<< "\n"
694 		<< "void main ()\n"
695 		<< "{\n"
696 		<< "    gl_PrimitiveCountNV = 1u;\n"
697 		<< "    lineColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
698 		<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-1.0f, 0.0f, 0.0f, 1.0f);\n"
699 		<< "    gl_MeshVerticesNV[1].gl_Position = vec4( 1.0f, 0.0f, 0.0f, 1.0f);\n"
700 		<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
701 		<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
702 		<< "}\n"
703 		;
704 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
705 }
706 
generateReferenceLevel()707 void SingleLineInstance::generateReferenceLevel ()
708 {
709 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
710 
711 	const auto iWidth		= static_cast<int>(m_params->width);
712 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
713 	const auto access		= m_referenceLevel->getAccess();
714 
715 	// Center row.
716 	for (int x = 0; x < iWidth; ++x)
717 		access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), x, halfHeight);
718 }
719 
720 // Verify drawing a single triangle.
721 class SingleTriangleCase : public MeshShaderMiscCase
722 {
723 public:
SingleTriangleCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)724 					SingleTriangleCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
725 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
726 					{}
727 
728 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
729 	TestInstance*	createInstance			(Context& context) const override;
730 };
731 
732 class SingleTriangleInstance : public MeshShaderMiscInstance
733 {
734 public:
SingleTriangleInstance(Context & context,const MiscTestParams * params)735 	SingleTriangleInstance (Context& context, const MiscTestParams* params)
736 		: MeshShaderMiscInstance (context, params)
737 	{}
738 
739 	void	generateReferenceLevel	() override;
740 };
741 
createInstance(Context & context) const742 TestInstance* SingleTriangleCase::createInstance (Context& context) const
743 {
744 	return new SingleTriangleInstance (context, m_params.get());
745 }
746 
initPrograms(vk::SourceCollections & programCollection) const747 void SingleTriangleCase::initPrograms (vk::SourceCollections& programCollection) const
748 {
749 	DE_ASSERT(!m_params->needsTaskShader());
750 
751 	MeshShaderMiscCase::initPrograms(programCollection);
752 
753 	const float halfPixelX = 2.0f / static_cast<float>(m_params->width);
754 	const float halfPixelY = 2.0f / static_cast<float>(m_params->height);
755 
756 	std::ostringstream mesh;
757 	mesh
758 		<< "#version 450\n"
759 		<< "#extension GL_NV_mesh_shader : enable\n"
760 		<< "\n"
761 		<< "layout(local_size_x=1) in;\n"
762 		<< "layout(triangles) out;\n"
763 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
764 		<< "\n"
765 		<< "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
766 		<< "\n"
767 		<< "void main ()\n"
768 		<< "{\n"
769 		<< "    gl_PrimitiveCountNV = 1u;\n"
770 		<< "    triangleColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
771 		<< "    gl_MeshVerticesNV[0].gl_Position = vec4(" <<  halfPixelY << ", " << -halfPixelX << ", 0.0f, 1.0f);\n"
772 		<< "    gl_MeshVerticesNV[1].gl_Position = vec4(" <<  halfPixelY << ", " <<  halfPixelX << ", 0.0f, 1.0f);\n"
773 		<< "    gl_MeshVerticesNV[2].gl_Position = vec4(" << -halfPixelY << ", 0.0f, 0.0f, 1.0f);\n"
774 		<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
775 		<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
776 		<< "    gl_PrimitiveIndicesNV[2] = 2;\n"
777 		<< "}\n"
778 		;
779 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
780 }
781 
generateReferenceLevel()782 void SingleTriangleInstance::generateReferenceLevel ()
783 {
784 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
785 
786 	const auto halfWidth	= static_cast<int>(m_params->width / 2u);
787 	const auto halfHeight	= static_cast<int>(m_params->height / 2u);
788 	const auto access		= m_referenceLevel->getAccess();
789 
790 	// Single pixel in the center.
791 	access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
792 }
793 
794 // Verify drawing the maximum number of points.
795 class MaxPointsCase : public MeshShaderMiscCase
796 {
797 public:
MaxPointsCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)798 					MaxPointsCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
799 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
800 					{}
801 
802 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
803 	TestInstance*	createInstance			(Context& context) const override;
804 };
805 
806 class MaxPointsInstance : public MeshShaderMiscInstance
807 {
808 public:
MaxPointsInstance(Context & context,const MiscTestParams * params)809 	MaxPointsInstance (Context& context, const MiscTestParams* params)
810 		: MeshShaderMiscInstance (context, params)
811 	{}
812 
813 	void	generateReferenceLevel	() override;
814 };
815 
createInstance(Context & context) const816 TestInstance* MaxPointsCase::createInstance (Context& context) const
817 {
818 	return new MaxPointsInstance (context, m_params.get());
819 }
820 
initPrograms(vk::SourceCollections & programCollection) const821 void MaxPointsCase::initPrograms (vk::SourceCollections& programCollection) const
822 {
823 	DE_ASSERT(!m_params->needsTaskShader());
824 
825 	MeshShaderMiscCase::initPrograms(programCollection);
826 
827 	// Fill a 16x16 image with 256 points. Each of the 32 local invocations will handle a segment of 8 pixels. Two segments per row.
828 	DE_ASSERT(m_params->width == 16u && m_params->height == 16u);
829 
830 	std::ostringstream mesh;
831 	mesh
832 		<< "#version 450\n"
833 		<< "#extension GL_NV_mesh_shader : enable\n"
834 		<< "\n"
835 		<< "layout(local_size_x=32) in;\n"
836 		<< "layout(points) out;\n"
837 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
838 		<< "\n"
839 		<< "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
840 		<< "\n"
841 		<< "void main ()\n"
842 		<< "{\n"
843 		<< "    gl_PrimitiveCountNV = 256u;\n"
844 		<< "    uint firstPixel = 8u * gl_LocalInvocationID.x;\n"
845 		<< "    uint row = firstPixel / 16u;\n"
846 		<< "    uint col = firstPixel % 16u;\n"
847 		<< "    float pixSize = 2.0f / 16.0f;\n"
848 		<< "    float yCoord = pixSize * (float(row) + 0.5f) - 1.0f;\n"
849 		<< "    float baseXCoord = pixSize * (float(col) + 0.5f) - 1.0f;\n"
850 		<< "    for (uint i = 0; i < 8u; i++) {\n"
851 		<< "        float xCoord = baseXCoord + pixSize * float(i);\n"
852 		<< "        uint pixId = firstPixel + i;\n"
853 		<< "        gl_MeshVerticesNV[pixId].gl_Position = vec4(xCoord, yCoord, 0.0f, 1.0f);\n"
854 		<< "        gl_MeshVerticesNV[pixId].gl_PointSize = 1.0f;\n"
855 		<< "        gl_PrimitiveIndicesNV[pixId] = pixId;\n"
856 		<< "        pointColor[pixId] = vec4(((xCoord + 1.0f) / 2.0f), ((yCoord + 1.0f) / 2.0f), 0.0f, 1.0f);\n"
857 		<< "    }\n"
858 		<< "}\n"
859 		;
860 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
861 }
862 
generateReferenceLevel()863 void MaxPointsInstance::generateReferenceLevel ()
864 {
865 	const auto format		= getOutputFormat();
866 	const auto tcuFormat	= mapVkFormat(format);
867 
868 	const auto iWidth		= static_cast<int>(m_params->width);
869 	const auto iHeight		= static_cast<int>(m_params->height);
870 	const auto fWidth		= static_cast<float>(m_params->width);
871 	const auto fHeight		= static_cast<float>(m_params->height);
872 
873 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
874 
875 	const auto access		= m_referenceLevel->getAccess();
876 
877 	// Fill with gradient like the shader does.
878 	for (int y = 0; y < iHeight; ++y)
879 	for (int x = 0; x < iWidth; ++x)
880 	{
881 		const tcu::Vec4 color (
882 			((static_cast<float>(x) + 0.5f) / fWidth),
883 			((static_cast<float>(y) + 0.5f) / fHeight),
884 			0.0f, 1.0f);
885 		access.setPixel(color, x, y);
886 	}
887 }
888 
889 // Verify drawing the maximum number of lines.
890 class MaxLinesCase : public MeshShaderMiscCase
891 {
892 public:
MaxLinesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)893 					MaxLinesCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
894 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
895 					{}
896 
897 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
898 	TestInstance*	createInstance			(Context& context) const override;
899 };
900 
901 class MaxLinesInstance : public MeshShaderMiscInstance
902 {
903 public:
MaxLinesInstance(Context & context,const MiscTestParams * params)904 	MaxLinesInstance (Context& context, const MiscTestParams* params)
905 		: MeshShaderMiscInstance (context, params)
906 	{}
907 
908 	void	generateReferenceLevel	() override;
909 };
910 
createInstance(Context & context) const911 TestInstance* MaxLinesCase::createInstance (Context& context) const
912 {
913 	return new MaxLinesInstance (context, m_params.get());
914 }
915 
initPrograms(vk::SourceCollections & programCollection) const916 void MaxLinesCase::initPrograms (vk::SourceCollections& programCollection) const
917 {
918 	DE_ASSERT(!m_params->needsTaskShader());
919 
920 	MeshShaderMiscCase::initPrograms(programCollection);
921 
922 	// Fill a 1x1020 image with 255 lines, each line being 4 pixels tall. Each invocation will generate ~8 lines.
923 	DE_ASSERT(m_params->width == 1u && m_params->height == 1020u);
924 
925 	std::ostringstream mesh;
926 	mesh
927 		<< "#version 450\n"
928 		<< "#extension GL_NV_mesh_shader : enable\n"
929 		<< "\n"
930 		<< "layout(local_size_x=32) in;\n"
931 		<< "layout(lines) out;\n"
932 		<< "layout(max_vertices=256, max_primitives=255) out;\n"
933 		<< "\n"
934 		<< "layout (location=0) out perprimitiveNV vec4 lineColor[];\n"
935 		<< "\n"
936 		<< "void main ()\n"
937 		<< "{\n"
938 		<< "    gl_PrimitiveCountNV = 255u;\n"
939 		<< "    uint firstLine = 8u * gl_LocalInvocationID.x;\n"
940 		<< "    for (uint i = 0u; i < 8u; i++) {\n"
941 		<< "        uint lineId = firstLine + i;\n"
942 		<< "        uint topPixel = 4u * lineId;\n"
943 		<< "        uint bottomPixel = 3u + topPixel;\n"
944 		<< "        if (bottomPixel < 1020u) {\n"
945 		<< "            float bottomCoord = ((float(bottomPixel) + 1.0f) / 1020.0) * 2.0 - 1.0;\n"
946 		<< "            gl_MeshVerticesNV[lineId + 1u].gl_Position = vec4(0.0, bottomCoord, 0.0f, 1.0f);\n"
947 		<< "            gl_PrimitiveIndicesNV[lineId * 2u] = lineId;\n"
948 		<< "            gl_PrimitiveIndicesNV[lineId * 2u + 1u] = lineId + 1u;\n"
949 		<< "            lineColor[lineId] = vec4(0.0f, 1.0f, float(lineId) / 255.0f, 1.0f);\n"
950 		<< "        } else {\n"
951 		<< "            // The last iteration of the last invocation emits the first point\n"
952 		<< "            gl_MeshVerticesNV[0].gl_Position = vec4(0.0, -1.0, 0.0f, 1.0f);\n"
953 		<< "        }\n"
954 		<< "    }\n"
955 		<< "}\n"
956 		;
957 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
958 }
959 
generateReferenceLevel()960 void MaxLinesInstance::generateReferenceLevel ()
961 {
962 	const auto format		= getOutputFormat();
963 	const auto tcuFormat	= mapVkFormat(format);
964 
965 	const auto iWidth		= static_cast<int>(m_params->width);
966 	const auto iHeight		= static_cast<int>(m_params->height);
967 
968 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
969 
970 	const auto access		= m_referenceLevel->getAccess();
971 
972 	// Fill lines, 4 pixels per line.
973 	const uint32_t kNumLines = 255u;
974 	const uint32_t kLineHeight = 4u;
975 
976 	for (uint32_t i = 0u; i < kNumLines; ++i)
977 	{
978 		const tcu::Vec4 color (0.0f, 1.0f, static_cast<float>(i) / static_cast<float>(kNumLines), 1.0f);
979 		for (uint32_t j = 0u; j < kLineHeight; ++j)
980 			access.setPixel(color, 0, i*kLineHeight + j);
981 	}
982 }
983 
984 // Verify drawing the maximum number of triangles.
985 class MaxTrianglesCase : public MeshShaderMiscCase
986 {
987 public:
MaxTrianglesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)988 					MaxTrianglesCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
989 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
990 					{}
991 
992 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
993 	TestInstance*	createInstance			(Context& context) const override;
994 };
995 
996 class MaxTrianglesInstance : public MeshShaderMiscInstance
997 {
998 public:
MaxTrianglesInstance(Context & context,const MiscTestParams * params)999 	MaxTrianglesInstance (Context& context, const MiscTestParams* params)
1000 		: MeshShaderMiscInstance (context, params)
1001 	{}
1002 
1003 	void	generateReferenceLevel	() override;
1004 };
1005 
createInstance(Context & context) const1006 TestInstance* MaxTrianglesCase::createInstance (Context& context) const
1007 {
1008 	return new MaxTrianglesInstance (context, m_params.get());
1009 }
1010 
initPrograms(vk::SourceCollections & programCollection) const1011 void MaxTrianglesCase::initPrograms (vk::SourceCollections& programCollection) const
1012 {
1013 	DE_ASSERT(!m_params->needsTaskShader());
1014 
1015 	MeshShaderMiscCase::initPrograms(programCollection);
1016 
1017 	// Fill a sufficiently large image with solid color. Generate a quarter of a circle with the center in the top left corner,
1018 	// using a triangle fan that advances from top to bottom. Each invocation will generate ~8 triangles.
1019 	std::ostringstream mesh;
1020 	mesh
1021 		<< "#version 450\n"
1022 		<< "#extension GL_NV_mesh_shader : enable\n"
1023 		<< "\n"
1024 		<< "layout(local_size_x=32) in;\n"
1025 		<< "layout(triangles) out;\n"
1026 		<< "layout(max_vertices=256, max_primitives=254) out;\n"
1027 		<< "\n"
1028 		<< "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
1029 		<< "\n"
1030 		<< "const float PI_2 = 1.57079632679489661923;\n"
1031 		<< "const float RADIUS = 4.5;\n"
1032 		<< "\n"
1033 		<< "void main ()\n"
1034 		<< "{\n"
1035 		<< "    gl_PrimitiveCountNV = 254u;\n"
1036 		<< "    uint firstTriangle = 8u * gl_LocalInvocationID.x;\n"
1037 		<< "    for (uint i = 0u; i < 8u; i++) {\n"
1038 		<< "        uint triangleId = firstTriangle + i;\n"
1039 		<< "        if (triangleId < 254u) {\n"
1040 		<< "            uint vertexId = triangleId + 2u;\n"
1041 		<< "            float angleProportion = float(vertexId - 1u) / 254.0f;\n"
1042 		<< "            float angle = PI_2 * angleProportion;\n"
1043 		<< "            float xCoord = cos(angle) * RADIUS - 1.0;\n"
1044 		<< "            float yCoord = sin(angle) * RADIUS - 1.0;\n"
1045 		<< "            gl_MeshVerticesNV[vertexId].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1046 		<< "            gl_PrimitiveIndicesNV[triangleId * 3u + 0u] = 0u;\n"
1047 		<< "            gl_PrimitiveIndicesNV[triangleId * 3u + 1u] = triangleId + 1u;\n"
1048 		<< "            gl_PrimitiveIndicesNV[triangleId * 3u + 2u] = triangleId + 2u;\n"
1049 		<< "            triangleColor[triangleId] = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n"
1050 		<< "        } else {\n"
1051 		<< "            // The last iterations of the last invocation emit the first two vertices\n"
1052 		<< "            uint vertexId = triangleId - 254u;\n"
1053 		<< "            if (vertexId == 0u) {\n"
1054 		<< "                gl_MeshVerticesNV[0u].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1055 		<< "            } else {\n"
1056 		<< "                gl_MeshVerticesNV[1u].gl_Position = vec4(RADIUS, -1.0, 0.0, 1.0);\n"
1057 		<< "            }\n"
1058 		<< "        }\n"
1059 		<< "    }\n"
1060 		<< "}\n"
1061 		;
1062 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
1063 }
1064 
generateReferenceLevel()1065 void MaxTrianglesInstance::generateReferenceLevel ()
1066 {
1067 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1068 }
1069 
1070 // Large work groups with many threads.
1071 class LargeWorkGroupCase : public MeshShaderMiscCase
1072 {
1073 public:
LargeWorkGroupCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1074 					LargeWorkGroupCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1075 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
1076 					{}
1077 
1078 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1079 	TestInstance*	createInstance			(Context& context) const override;
1080 
1081 	static constexpr uint32_t kLocalInvocations = 32u;
1082 };
1083 
1084 class LargeWorkGroupInstance : public MeshShaderMiscInstance
1085 {
1086 public:
LargeWorkGroupInstance(Context & context,const MiscTestParams * params)1087 	LargeWorkGroupInstance (Context& context, const MiscTestParams* params)
1088 		: MeshShaderMiscInstance (context, params)
1089 	{}
1090 
1091 	void	generateReferenceLevel	() override;
1092 };
1093 
createInstance(Context & context) const1094 TestInstance* LargeWorkGroupCase::createInstance (Context& context) const
1095 {
1096 	return new LargeWorkGroupInstance(context, m_params.get());
1097 }
1098 
generateReferenceLevel()1099 void LargeWorkGroupInstance::generateReferenceLevel ()
1100 {
1101 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1102 }
1103 
initPrograms(vk::SourceCollections & programCollection) const1104 void LargeWorkGroupCase::initPrograms (vk::SourceCollections& programCollection) const
1105 {
1106 	const auto useTaskShader	= m_params->needsTaskShader();
1107 	const auto taskMultiplier	= (useTaskShader ? m_params->taskCount.get() : 1u);
1108 
1109 	// Add the frag shader.
1110 	MeshShaderMiscCase::initPrograms(programCollection);
1111 
1112 	std::ostringstream taskData;
1113 	taskData
1114 		<< "taskNV TaskData {\n"
1115 		<< "    uint parentTask[" << kLocalInvocations << "];\n"
1116 		<< "} td;\n"
1117 		;
1118 	const auto taskDataStr = taskData.str();
1119 
1120 	if (useTaskShader)
1121 	{
1122 		std::ostringstream task;
1123 		task
1124 			<< "#version 450\n"
1125 			<< "#extension GL_NV_mesh_shader : enable\n"
1126 			<< "\n"
1127 			<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1128 			<< "\n"
1129 			<< "out " << taskDataStr
1130 			<< "\n"
1131 			<< "void main () {\n"
1132 			<< "    gl_TaskCountNV = " << m_params->meshCount << ";\n"
1133 			<< "    td.parentTask[gl_LocalInvocationID.x] = gl_WorkGroupID.x;\n"
1134 			<< "}\n"
1135 			;
1136 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
1137 	}
1138 
1139 	// Needed for the code below to work.
1140 	DE_ASSERT(m_params->width * m_params->height == taskMultiplier * m_params->meshCount * kLocalInvocations);
1141 	DE_UNREF(taskMultiplier); // For release builds.
1142 
1143 	// Emit one point per framebuffer pixel. The number of jobs (kLocalInvocations in each mesh shader work group, multiplied by the
1144 	// number of mesh work groups emitted by each task work group) must be the same as the total framebuffer size. Calculate a job
1145 	// ID corresponding to the current mesh shader invocation, and assign a pixel position to it. Draw a point at that position.
1146 	std::ostringstream mesh;
1147 	mesh
1148 		<< "#version 450\n"
1149 		<< "#extension GL_NV_mesh_shader : enable\n"
1150 		<< "\n"
1151 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1152 		<< "layout (points) out;\n"
1153 		<< "layout (max_vertices=" << kLocalInvocations << ", max_primitives=" << kLocalInvocations << ") out;\n"
1154 		<< "\n"
1155 		<< (useTaskShader ? "in " + taskDataStr : "")
1156 		<< "\n"
1157 		<< "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
1158 		<< "\n"
1159 		<< "void main () {\n"
1160 		;
1161 
1162 	if (useTaskShader)
1163 	{
1164 		mesh
1165 			<< "    uint parentTask = td.parentTask[0];\n"
1166 			<< "    if (td.parentTask[gl_LocalInvocationID.x] != parentTask) {\n"
1167 			<< "        return;\n"
1168 			<< "    }\n"
1169 			;
1170 	}
1171 	else
1172 	{
1173 		mesh << "    uint parentTask = 0;\n";
1174 	}
1175 
1176 	mesh
1177 		<< "    gl_PrimitiveCountNV = " << kLocalInvocations << ";\n"
1178 		<< "    uint jobId = ((parentTask * " << m_params->meshCount << ") + gl_WorkGroupID.x) * " << kLocalInvocations << " + gl_LocalInvocationID.x;\n"
1179 		<< "    uint row = jobId / " << m_params->width << ";\n"
1180 		<< "    uint col = jobId % " << m_params->width << ";\n"
1181 		<< "    float yCoord = (float(row + 0.5) / " << m_params->height << ".0) * 2.0 - 1.0;\n"
1182 		<< "    float xCoord = (float(col + 0.5) / " << m_params->width << ".0) * 2.0 - 1.0;\n"
1183 		<< "    gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1184 		<< "    gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_PointSize = 1.0;\n"
1185 		<< "    gl_PrimitiveIndicesNV[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
1186 		<< "    pointColor[gl_LocalInvocationID.x] = vec4(0.0, 0.0, 1.0, 1.0);\n"
1187 		<< "}\n"
1188 		;
1189 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
1190 }
1191 
1192 // Tests that generate no primitives of a given type.
1193 enum class PrimitiveType { POINTS=0, LINES, TRIANGLES };
1194 
primitiveTypeName(PrimitiveType primitiveType)1195 std::string primitiveTypeName (PrimitiveType primitiveType)
1196 {
1197 	std::string primitiveName;
1198 
1199 	switch (primitiveType)
1200 	{
1201 	case PrimitiveType::POINTS:		primitiveName = "points";		break;
1202 	case PrimitiveType::LINES:		primitiveName = "lines";		break;
1203 	case PrimitiveType::TRIANGLES:	primitiveName = "triangles";	break;
1204 	default: DE_ASSERT(false); break;
1205 	}
1206 
1207 	return primitiveName;
1208 }
1209 
1210 struct NoPrimitivesParams : public MiscTestParams
1211 {
1212 	PrimitiveType primitiveType;
1213 };
1214 
1215 class NoPrimitivesCase : public MeshShaderMiscCase
1216 {
1217 public:
NoPrimitivesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1218 					NoPrimitivesCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1219 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
1220 					{}
1221 
1222 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1223 	TestInstance*	createInstance			(Context& context) const override;
1224 };
1225 
1226 class NoPrimitivesInstance : public MeshShaderMiscInstance
1227 {
1228 public:
NoPrimitivesInstance(Context & context,const MiscTestParams * params)1229 	NoPrimitivesInstance (Context& context, const MiscTestParams* params)
1230 		: MeshShaderMiscInstance (context, params)
1231 	{}
1232 
1233 	void	generateReferenceLevel	() override;
1234 };
1235 
generateReferenceLevel()1236 void NoPrimitivesInstance::generateReferenceLevel ()
1237 {
1238 	// No primitives: clear color.
1239 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
1240 }
1241 
createInstance(Context & context) const1242 TestInstance* NoPrimitivesCase::createInstance (Context& context) const
1243 {
1244 	return new NoPrimitivesInstance(context, m_params.get());
1245 }
1246 
initPrograms(vk::SourceCollections & programCollection) const1247 void NoPrimitivesCase::initPrograms (vk::SourceCollections& programCollection) const
1248 {
1249 	const auto params = dynamic_cast<NoPrimitivesParams*>(m_params.get());
1250 
1251 	DE_ASSERT(params);
1252 	DE_ASSERT(!params->needsTaskShader());
1253 
1254 	const auto primitiveName = primitiveTypeName(params->primitiveType);
1255 
1256 	std::ostringstream mesh;
1257 	mesh
1258 		<< "#version 450\n"
1259 		<< "#extension GL_NV_mesh_shader : enable\n"
1260 		<< "\n"
1261 		<< "layout (local_size_x=32) in;\n"
1262 		<< "layout (" << primitiveName << ") out;\n"
1263 		<< "layout (max_vertices=256, max_primitives=256) out;\n"
1264 		<< "\n"
1265 		<< "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
1266 		<< "\n"
1267 		<< "void main () {\n"
1268 		<< "    gl_PrimitiveCountNV = 0u;\n"
1269 		<< "}\n"
1270 		;
1271 
1272 	MeshShaderMiscCase::initPrograms(programCollection);
1273 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
1274 }
1275 
1276 class NoPrimitivesExtraWritesCase : public NoPrimitivesCase
1277 {
1278 public:
NoPrimitivesExtraWritesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1279 					NoPrimitivesExtraWritesCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1280 						: NoPrimitivesCase (testCtx, name, description, std::move(params))
1281 					{}
1282 
1283 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1284 
1285 	static constexpr uint32_t kLocalInvocations = 32u;
1286 };
1287 
initPrograms(vk::SourceCollections & programCollection) const1288 void NoPrimitivesExtraWritesCase::initPrograms (vk::SourceCollections& programCollection) const
1289 {
1290 	const auto params = dynamic_cast<NoPrimitivesParams*>(m_params.get());
1291 
1292 	DE_ASSERT(params);
1293 	DE_ASSERT(m_params->needsTaskShader());
1294 
1295 	std::ostringstream taskData;
1296 	taskData
1297 		<< "taskNV TaskData {\n"
1298 		<< "    uint localInvocations[" << kLocalInvocations << "];\n"
1299 		<< "} td;\n"
1300 		;
1301 	const auto taskDataStr = taskData.str();
1302 
1303 	std::ostringstream task;
1304 	task
1305 		<< "#version 450\n"
1306 		<< "#extension GL_NV_mesh_shader : enable\n"
1307 		<< "\n"
1308 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1309 		<< "\n"
1310 		<< "out " << taskDataStr
1311 		<< "\n"
1312 		<< "void main () {\n"
1313 		<< "    gl_TaskCountNV = " << params->meshCount << ";\n"
1314 		<< "    td.localInvocations[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
1315 		<< "}\n"
1316 		;
1317 	programCollection.glslSources.add("task") << glu::TaskSource(task.str());
1318 
1319 	const auto primitiveName = primitiveTypeName(params->primitiveType);
1320 
1321 	// Otherwise the shader would be illegal.
1322 	DE_ASSERT(kLocalInvocations > 2u);
1323 
1324 	uint32_t maxPrimitives = 0u;
1325 	switch (params->primitiveType)
1326 	{
1327 	case PrimitiveType::POINTS:		maxPrimitives = kLocalInvocations - 0u;	break;
1328 	case PrimitiveType::LINES:		maxPrimitives = kLocalInvocations - 1u;	break;
1329 	case PrimitiveType::TRIANGLES:	maxPrimitives = kLocalInvocations - 2u;	break;
1330 	default: DE_ASSERT(false); break;
1331 	}
1332 
1333 	const std::string pointSizeDecl	= ((params->primitiveType == PrimitiveType::POINTS)
1334 									? "        gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_PointSize = 1.0;\n"
1335 									: "");
1336 
1337 	std::ostringstream mesh;
1338 	mesh
1339 		<< "#version 450\n"
1340 		<< "#extension GL_NV_mesh_shader : enable\n"
1341 		<< "\n"
1342 		<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1343 		<< "layout (" << primitiveName << ") out;\n"
1344 		<< "layout (max_vertices=" << kLocalInvocations << ", max_primitives=" << maxPrimitives << ") out;\n"
1345 		<< "\n"
1346 		<< "in " << taskDataStr
1347 		<< "\n"
1348 		<< "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
1349 		<< "\n"
1350 		<< "shared uint sumOfIds;\n"
1351 		<< "\n"
1352 		<< "const float PI_2 = 1.57079632679489661923;\n"
1353 		<< "const float RADIUS = 1.0f;\n"
1354 		<< "\n"
1355 		<< "void main ()\n"
1356 		<< "{\n"
1357 		<< "    sumOfIds = 0u;\n"
1358 		<< "    barrier();\n"
1359 		<< "    atomicAdd(sumOfIds, td.localInvocations[gl_LocalInvocationID.x]);\n"
1360 		<< "    barrier();\n"
1361 		<< "    // This should dynamically give 0\n"
1362 		<< "    gl_PrimitiveCountNV = sumOfIds - (" << kLocalInvocations * (kLocalInvocations - 1u) / 2u << ");\n"
1363 		<< "\n"
1364 		<< "    // Emit points and primitives to the arrays in any case\n"
1365 		<< "    if (gl_LocalInvocationID.x > 0u) {\n"
1366 		<< "        float proportion = (float(gl_LocalInvocationID.x - 1u) + 0.5f) / float(" << kLocalInvocations << " - 1u);\n"
1367 		<< "        float angle = PI_2 * proportion;\n"
1368 		<< "        float xCoord = cos(angle) * RADIUS - 1.0;\n"
1369 		<< "        float yCoord = sin(angle) * RADIUS - 1.0;\n"
1370 		<< "        gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
1371 		<< pointSizeDecl
1372 		<< "    } else {\n"
1373 		<< "        gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1374 		<< pointSizeDecl
1375 		<< "    }\n"
1376 		<< "    uint primitiveId = max(gl_LocalInvocationID.x, " << (maxPrimitives - 1u) << ");\n"
1377 		<< "    primitiveColor[primitiveId] = vec4(0.0, 0.0, 1.0, 1.0);\n"
1378 		;
1379 
1380 	if (params->primitiveType == PrimitiveType::POINTS)
1381 	{
1382 		mesh
1383 			<< "    gl_PrimitiveIndicesNV[primitiveId] = primitiveId;\n"
1384 			;
1385 	}
1386 	else if (params->primitiveType == PrimitiveType::LINES)
1387 	{
1388 		mesh
1389 			<< "    gl_PrimitiveIndicesNV[primitiveId * 2u + 0u] = primitiveId + 0u;\n"
1390 			<< "    gl_PrimitiveIndicesNV[primitiveId * 2u + 1u] = primitiveId + 1u;\n"
1391 			;
1392 	}
1393 	else if (params->primitiveType == PrimitiveType::TRIANGLES)
1394 	{
1395 		mesh
1396 			<< "    gl_PrimitiveIndicesNV[primitiveId * 3u + 0u] = 0u;\n"
1397 			<< "    gl_PrimitiveIndicesNV[primitiveId * 3u + 1u] = primitiveId + 1u;\n"
1398 			<< "    gl_PrimitiveIndicesNV[primitiveId * 3u + 2u] = primitiveId + 3u;\n"
1399 			;
1400 	}
1401 	else
1402 		DE_ASSERT(false);
1403 
1404 	mesh
1405 		<< "}\n"
1406 		;
1407 
1408 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
1409 
1410 	MeshShaderMiscCase::initPrograms(programCollection);
1411 }
1412 
1413 // Case testing barrier().
1414 class SimpleBarrierCase : public MeshShaderMiscCase
1415 {
1416 public:
SimpleBarrierCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1417 					SimpleBarrierCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1418 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
1419 					{}
1420 
1421 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1422 	TestInstance*	createInstance			(Context& context) const override;
1423 
1424 	static constexpr uint32_t kLocalInvocations = 32u;
1425 };
1426 
1427 class SimpleBarrierInstance : public MeshShaderMiscInstance
1428 {
1429 public:
SimpleBarrierInstance(Context & context,const MiscTestParams * params)1430 	SimpleBarrierInstance (Context& context, const MiscTestParams* params)
1431 		: MeshShaderMiscInstance (context, params)
1432 	{}
1433 
1434 	void	generateReferenceLevel	() override;
1435 };
1436 
createInstance(Context & context) const1437 TestInstance* SimpleBarrierCase::createInstance (Context& context) const
1438 {
1439 	return new SimpleBarrierInstance(context, m_params.get());
1440 }
1441 
generateReferenceLevel()1442 void SimpleBarrierInstance::generateReferenceLevel ()
1443 {
1444 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1445 }
1446 
initPrograms(vk::SourceCollections & programCollection) const1447 void SimpleBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
1448 {
1449 	// Generate frag shader.
1450 	MeshShaderMiscCase::initPrograms(programCollection);
1451 
1452 	DE_ASSERT(m_params->meshCount == 1u);
1453 	DE_ASSERT(m_params->width == 1u && m_params->height == 1u);
1454 
1455 	std::ostringstream meshPrimData;
1456 	meshPrimData
1457 			<< "gl_PrimitiveCountNV = 1u;\n"
1458 			<< "gl_MeshVerticesNV[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1459 			<< "gl_MeshVerticesNV[0].gl_PointSize = 1.0;\n"
1460 			<< "primitiveColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
1461 			<< "gl_PrimitiveIndicesNV[0] = 0;\n"
1462 			;
1463 	const std::string meshPrimStr	= meshPrimData.str();
1464 
1465 	const std::string taskOK		= "gl_TaskCountNV = 1u;\n";
1466 	const std::string taskFAIL		= "gl_TaskCountNV = 0u;\n";
1467 
1468 	const std::string meshOK		= meshPrimStr;
1469 	const std::string meshFAIL		= "gl_PrimitiveCountNV = 0u;\n";
1470 
1471 	const std::string okStatement	= (m_params->needsTaskShader() ? taskOK : meshOK);
1472 	const std::string failStatement	= (m_params->needsTaskShader() ? taskFAIL : meshFAIL);
1473 
1474 	const std::string	sharedDecl = "shared uint counter;\n\n";
1475 	std::ostringstream	verification;
1476 	verification
1477 		<< "counter = 0;\n"
1478 		<< "barrier();\n"
1479 		<< "atomicAdd(counter, 1u);\n"
1480 		<< "barrier();\n"
1481 		<< "if (gl_LocalInvocationID.x == 0u) {\n"
1482 		<< "    if (counter == " << kLocalInvocations << ") {\n"
1483 		<< "\n"
1484 		<< okStatement
1485 		<< "\n"
1486 		<< "    } else {\n"
1487 		<< "\n"
1488 		<< failStatement
1489 		<< "\n"
1490 		<< "    }\n"
1491 		<< "}\n"
1492 		;
1493 
1494 	// The mesh shader is very similar in both cases, so we use a template.
1495 	std::ostringstream meshTemplateStr;
1496 	meshTemplateStr
1497 		<< "#version 450\n"
1498 		<< "#extension GL_NV_mesh_shader : enable\n"
1499 		<< "\n"
1500 		<< "layout (local_size_x=${LOCAL_SIZE}) in;\n"
1501 		<< "layout (points) out;\n"
1502 		<< "layout (max_vertices=1, max_primitives=1) out;\n"
1503 		<< "\n"
1504 		<< "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
1505 		<< "\n"
1506 		<< "${GLOBALS:opt}"
1507 		<< "void main ()\n"
1508 		<< "{\n"
1509 		<< "${BODY}"
1510 		<< "}\n"
1511 		;
1512 	const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
1513 
1514 	if (m_params->needsTaskShader())
1515 	{
1516 		std::ostringstream task;
1517 		task
1518 			<< "#version 450\n"
1519 			<< "#extension GL_NV_mesh_shader : enable\n"
1520 			<< "\n"
1521 			<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1522 			<< "\n"
1523 			<< sharedDecl
1524 			<< "void main ()\n"
1525 			<< "{\n"
1526 			<< verification.str()
1527 			<< "}\n"
1528 			;
1529 
1530 		std::map<std::string, std::string> replacements;
1531 		replacements["LOCAL_SIZE"]	= "1";
1532 		replacements["BODY"]		= meshPrimStr;
1533 
1534 		const auto meshStr = meshTemplate.specialize(replacements);
1535 
1536 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
1537 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
1538 	}
1539 	else
1540 	{
1541 		std::map<std::string, std::string> replacements;
1542 		replacements["LOCAL_SIZE"]	= std::to_string(kLocalInvocations);
1543 		replacements["BODY"]		= verification.str();
1544 		replacements["GLOBALS"]		= sharedDecl;
1545 
1546 		const auto meshStr = meshTemplate.specialize(replacements);
1547 
1548 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
1549 	}
1550 }
1551 
1552 // Case testing memoryBarrierShared() and groupMemoryBarrier().
1553 enum class MemoryBarrierType { SHARED = 0, GROUP };
1554 
1555 struct MemoryBarrierParams : public MiscTestParams
1556 {
1557 	MemoryBarrierType memBarrierType;
1558 
glslFuncvkt::MeshShader::__anona67b1ba90111::MemoryBarrierParams1559 	std::string glslFunc () const
1560 	{
1561 		std::string funcName;
1562 
1563 		switch (memBarrierType)
1564 		{
1565 		case MemoryBarrierType::SHARED:		funcName = "memoryBarrierShared";	break;
1566 		case MemoryBarrierType::GROUP:		funcName = "groupMemoryBarrier";	break;
1567 		default: DE_ASSERT(false); break;
1568 		}
1569 
1570 		return funcName;
1571 	}
1572 
1573 };
1574 
1575 class MemoryBarrierCase : public MeshShaderMiscCase
1576 {
1577 public:
MemoryBarrierCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1578 					MemoryBarrierCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1579 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
1580 					{}
1581 
1582 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1583 	TestInstance*	createInstance			(Context& context) const override;
1584 
1585 	static constexpr uint32_t kLocalInvocations = 2u;
1586 };
1587 
1588 class MemoryBarrierInstance : public MeshShaderMiscInstance
1589 {
1590 public:
MemoryBarrierInstance(Context & context,const MiscTestParams * params)1591 	MemoryBarrierInstance (Context& context, const MiscTestParams* params)
1592 		: MeshShaderMiscInstance (context, params)
1593 	{}
1594 
1595 	void	generateReferenceLevel	() override;
1596 	bool	verifyResult			(const tcu::ConstPixelBufferAccess& resultAccess) const override;
1597 
1598 protected:
1599 	// Allow two possible outcomes.
1600 	std::unique_ptr<tcu::TextureLevel>	m_referenceLevel2;
1601 };
1602 
createInstance(Context & context) const1603 TestInstance* MemoryBarrierCase::createInstance (Context& context) const
1604 {
1605 	return new MemoryBarrierInstance(context, m_params.get());
1606 }
1607 
generateReferenceLevel()1608 void MemoryBarrierInstance::generateReferenceLevel ()
1609 {
1610 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
1611 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), m_referenceLevel2);
1612 }
1613 
verifyResult(const tcu::ConstPixelBufferAccess & resultAccess) const1614 bool MemoryBarrierInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
1615 {
1616 	// Any of the two results is considered valid.
1617 	// Clarify what we are checking in the logs; otherwise, they could be confusing.
1618 	auto& log = m_context.getTestContext().getLog();
1619 	const std::vector<tcu::TextureLevel*> levels = { m_referenceLevel.get(), m_referenceLevel2.get() };
1620 
1621 	bool good = false;
1622 	for (size_t i = 0; i < levels.size(); ++i)
1623 	{
1624 		log << tcu::TestLog::Message << "Comparing result with reference " << i << "..." << tcu::TestLog::EndMessage;
1625 		const auto success = MeshShaderMiscInstance::verifyResult(resultAccess, *levels[i]);
1626 		if (success)
1627 		{
1628 			log << tcu::TestLog::Message << "Match! The test has passed" << tcu::TestLog::EndMessage;
1629 			good = true;
1630 			break;
1631 		}
1632 	}
1633 
1634 	return good;
1635 }
1636 
initPrograms(vk::SourceCollections & programCollection) const1637 void MemoryBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
1638 {
1639 	const auto params = dynamic_cast<MemoryBarrierParams*>(m_params.get());
1640 	DE_ASSERT(params);
1641 
1642 	// Generate frag shader.
1643 	MeshShaderMiscCase::initPrograms(programCollection);
1644 
1645 	DE_ASSERT(params->meshCount == 1u);
1646 	DE_ASSERT(params->width == 1u && params->height == 1u);
1647 
1648 	const bool taskShader = params->needsTaskShader();
1649 
1650 	const std::string	taskDataDecl	= "taskNV TaskData { float blue; } td;\n\n";
1651 	const std::string	inTaskData		= "in " + taskDataDecl;
1652 	const std::string	outTaskData		= "out " + taskDataDecl;
1653 	const auto			barrierFunc		= params->glslFunc();
1654 
1655 	std::ostringstream meshPrimData;
1656 	meshPrimData
1657 			<< "gl_PrimitiveCountNV = 1u;\n"
1658 			<< "gl_MeshVerticesNV[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1659 			<< "gl_MeshVerticesNV[0].gl_PointSize = 1.0;\n"
1660 			<< "primitiveColor[0] = vec4(0.0, 0.0, " << (taskShader ? "td.blue" : "float(iterations % 2u)") << ", 1.0);\n"
1661 			<< "gl_PrimitiveIndicesNV[0] = 0;\n"
1662 			;
1663 	const std::string meshPrimStr	= meshPrimData.str();
1664 
1665 	const std::string taskAction	= "gl_TaskCountNV = 1u;\ntd.blue = float(iterations % 2u);\n";
1666 	const std::string meshAction	= meshPrimStr;
1667 	const std::string action		= (taskShader ? taskAction : meshAction);
1668 
1669 	const std::string	sharedDecl = "shared uint flags[2];\n\n";
1670 	std::ostringstream	verification;
1671 	verification
1672 		<< "flags[gl_LocalInvocationID.x] = 0u;\n"
1673 		<< "barrier();\n"
1674 		<< "flags[gl_LocalInvocationID.x] = 1u;\n"
1675 		<<  barrierFunc << "();\n"
1676 		<< "uint otherInvocation = 1u - gl_LocalInvocationID.x;\n"
1677 		<< "uint iterations = 0u;\n"
1678 		<< "while (flags[otherInvocation] != 1u) {\n"
1679 		<< "    iterations++;\n"
1680 		<< "}\n"
1681 		<< "if (gl_LocalInvocationID.x == 0u) {\n"
1682 		<< "\n"
1683 		<< action
1684 		<< "\n"
1685 		<< "}\n"
1686 		;
1687 
1688 	// The mesh shader is very similar in both cases, so we use a template.
1689 	std::ostringstream meshTemplateStr;
1690 	meshTemplateStr
1691 		<< "#version 450\n"
1692 		<< "#extension GL_NV_mesh_shader : enable\n"
1693 		<< "\n"
1694 		<< "layout (local_size_x=${LOCAL_SIZE}) in;\n"
1695 		<< "layout (points) out;\n"
1696 		<< "layout (max_vertices=1, max_primitives=1) out;\n"
1697 		<< "\n"
1698 		<< "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
1699 		<< "\n"
1700 		<< "${GLOBALS}"
1701 		<< "void main ()\n"
1702 		<< "{\n"
1703 		<< "${BODY}"
1704 		<< "}\n"
1705 		;
1706 	const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
1707 
1708 	if (params->needsTaskShader())
1709 	{
1710 		std::ostringstream task;
1711 		task
1712 			<< "#version 450\n"
1713 			<< "#extension GL_NV_mesh_shader : enable\n"
1714 			<< "\n"
1715 			<< "layout (local_size_x=" << kLocalInvocations << ") in;\n"
1716 			<< "\n"
1717 			<< sharedDecl
1718 			<< outTaskData
1719 			<< "void main ()\n"
1720 			<< "{\n"
1721 			<< verification.str()
1722 			<< "}\n"
1723 			;
1724 
1725 		std::map<std::string, std::string> replacements;
1726 		replacements["LOCAL_SIZE"]	= "1";
1727 		replacements["BODY"]		= meshPrimStr;
1728 		replacements["GLOBALS"]		= inTaskData;
1729 
1730 		const auto meshStr = meshTemplate.specialize(replacements);
1731 
1732 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
1733 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
1734 	}
1735 	else
1736 	{
1737 		std::map<std::string, std::string> replacements;
1738 		replacements["LOCAL_SIZE"]	= std::to_string(kLocalInvocations);
1739 		replacements["BODY"]		= verification.str();
1740 		replacements["GLOBALS"]		= sharedDecl;
1741 
1742 		const auto meshStr = meshTemplate.specialize(replacements);
1743 
1744 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
1745 	}
1746 }
1747 
1748 class CustomAttributesCase : public MeshShaderMiscCase
1749 {
1750 public:
CustomAttributesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)1751 					CustomAttributesCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
1752 						: MeshShaderMiscCase(testCtx, name, description, std::move(params)) {}
~CustomAttributesCase(void)1753 	virtual			~CustomAttributesCase		(void) {}
1754 
1755 	TestInstance*	createInstance				(Context& context) const override;
1756 	void			checkSupport				(Context& context) const override;
1757 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
1758 };
1759 
1760 class CustomAttributesInstance : public MeshShaderMiscInstance
1761 {
1762 public:
CustomAttributesInstance(Context & context,const MiscTestParams * params)1763 						CustomAttributesInstance	(Context& context, const MiscTestParams* params)
1764 							: MeshShaderMiscInstance(context, params) {}
~CustomAttributesInstance(void)1765 	virtual				~CustomAttributesInstance	(void) {}
1766 
1767 	void				generateReferenceLevel		() override;
1768 	tcu::TestStatus		iterate						(void) override;
1769 };
1770 
createInstance(Context & context) const1771 TestInstance* CustomAttributesCase::createInstance (Context& context) const
1772 {
1773 	return new CustomAttributesInstance(context, m_params.get());
1774 }
1775 
checkSupport(Context & context) const1776 void CustomAttributesCase::checkSupport (Context& context) const
1777 {
1778 	MeshShaderMiscCase::checkSupport(context);
1779 
1780 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
1781 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
1782 }
1783 
initPrograms(vk::SourceCollections & programCollection) const1784 void CustomAttributesCase::initPrograms (vk::SourceCollections& programCollection) const
1785 {
1786 	std::ostringstream frag;
1787 	frag
1788 		<< "#version 450\n"
1789 		<< "#extension GL_NV_mesh_shader : enable\n"
1790 		<< "\n"
1791 		<< "layout (location=0) in vec4 customAttribute1;\n"
1792 		<< "layout (location=1) in flat float customAttribute2;\n"
1793 		<< "layout (location=2) in flat int customAttribute3;\n"
1794 		<< "\n"
1795 		<< "layout (location=3) in perprimitiveNV flat uvec4 customAttribute4;\n"
1796 		<< "layout (location=4) in perprimitiveNV float customAttribute5;\n"
1797 		<< "\n"
1798 		<< "layout (location=0) out vec4 outColor;\n"
1799 		<< "\n"
1800 		<< "void main ()\n"
1801 		<< "{\n"
1802 		<< "    bool goodPrimitiveID = (gl_PrimitiveID == 1000 || gl_PrimitiveID == 1001);\n"
1803 		<< "    bool goodViewportIndex = (gl_ViewportIndex == 1);\n"
1804 		<< "    bool goodCustom1 = (customAttribute1.x >= 0.25 && customAttribute1.x <= 0.5 &&\n"
1805 		<< "                        customAttribute1.y >= 0.5  && customAttribute1.y <= 1.0 &&\n"
1806 		<< "                        customAttribute1.z >= 10.0 && customAttribute1.z <= 20.0 &&\n"
1807 		<< "                        customAttribute1.w == 3.0);\n"
1808 		<< "    bool goodCustom2 = (customAttribute2 == 1.0 || customAttribute2 == 2.0);\n"
1809 		<< "    bool goodCustom3 = (customAttribute3 == 3 || customAttribute3 == 4);\n"
1810 		<< "    bool goodCustom4 = ((gl_PrimitiveID == 1000 && customAttribute4 == uvec4(100, 101, 102, 103)) ||\n"
1811 		<< "                        (gl_PrimitiveID == 1001 && customAttribute4 == uvec4(200, 201, 202, 203)));\n"
1812 		<< "    bool goodCustom5 = ((gl_PrimitiveID == 1000 && customAttribute5 == 6.0) ||\n"
1813 		<< "                        (gl_PrimitiveID == 1001 && customAttribute5 == 7.0));\n"
1814 		<< "    \n"
1815 		<< "    if (goodPrimitiveID && goodViewportIndex && goodCustom1 && goodCustom2 && goodCustom3 && goodCustom4 && goodCustom5) {\n"
1816 		<< "        outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1817 		<< "    } else {\n"
1818 		<< "        outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
1819 		<< "    }\n"
1820 		<< "}\n"
1821 		;
1822 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1823 
1824 	std::ostringstream pvdDataDeclStream;
1825 	pvdDataDeclStream
1826 		<< "    vec4 positions[4];\n"
1827 		<< "    float pointSizes[4];\n"
1828 		<< "    float clipDistances[4];\n"
1829 		<< "    vec4 custom1[4];\n"
1830 		<< "    float custom2[4];\n"
1831 		<< "    int custom3[4];\n"
1832 		;
1833 	const auto pvdDataDecl = pvdDataDeclStream.str();
1834 
1835 	std::ostringstream ppdDataDeclStream;
1836 	ppdDataDeclStream
1837 		<< "    int primitiveIds[2];\n"
1838 		<< "    int viewportIndices[2];\n"
1839 		<< "    uvec4 custom4[2];\n"
1840 		<< "    float custom5[2];\n"
1841 		;
1842 	const auto ppdDataDecl = ppdDataDeclStream.str();
1843 
1844 	std::ostringstream bindingsDeclStream;
1845 	bindingsDeclStream
1846 		<< "layout (set=0, binding=0, std430) buffer PerVertexData {\n"
1847 		<< pvdDataDecl
1848 		<< "} pvd;\n"
1849 		<< "layout (set=0, binding=1) uniform PerPrimitiveData {\n"
1850 		<< ppdDataDecl
1851 		<< "} ppd;\n"
1852 		<< "\n"
1853 		;
1854 	const auto bindingsDecl = bindingsDeclStream.str();
1855 
1856 	std::ostringstream taskDataStream;
1857 	taskDataStream
1858 		<< "taskNV TaskData {\n"
1859 		<< pvdDataDecl
1860 		<< ppdDataDecl
1861 		<< "} td;\n"
1862 		<< "\n"
1863 		;
1864 	const auto taskDataDecl = taskDataStream.str();
1865 
1866 	const auto taskShader = m_params->needsTaskShader();
1867 
1868 	const auto meshPvdPrefix = (taskShader ? "td" : "pvd");
1869 	const auto meshPpdPrefix = (taskShader ? "td" : "ppd");
1870 
1871 	std::ostringstream mesh;
1872 	mesh
1873 		<< "#version 450\n"
1874 		<< "#extension GL_NV_mesh_shader : enable\n"
1875 		<< "\n"
1876 		<< "layout (local_size_x=1) in;\n"
1877 		<< "layout (max_primitives=2, max_vertices=4) out;\n"
1878 		<< "layout (triangles) out;\n"
1879 		<< "\n"
1880 		<< "out gl_MeshPerVertexNV {\n"
1881 		<< "    vec4  gl_Position;\n"
1882 		<< "    float gl_PointSize;\n"
1883 		<< "    float gl_ClipDistance[1];\n"
1884 		<< "} gl_MeshVerticesNV[];\n"
1885 		<< "\n"
1886 		<< "layout (location=0) out vec4 customAttribute1[];\n"
1887 		<< "layout (location=1) out flat float customAttribute2[];\n"
1888 		<< "layout (location=2) out int customAttribute3[];\n"
1889 		<< "\n"
1890 		<< "layout (location=3) out perprimitiveNV uvec4 customAttribute4[];\n"
1891 		<< "layout (location=4) out perprimitiveNV float customAttribute5[];\n"
1892 		<< "\n"
1893 		<< "out perprimitiveNV gl_MeshPerPrimitiveNV {\n"
1894 		<< "  int gl_PrimitiveID;\n"
1895 		<< "  int gl_ViewportIndex;\n"
1896 		<< "} gl_MeshPrimitivesNV[];\n"
1897 		<< "\n"
1898 		<< (taskShader ? "in " + taskDataDecl : bindingsDecl)
1899 		<< "void main ()\n"
1900 		<< "{\n"
1901 		<< "    gl_PrimitiveCountNV = 2u;\n"
1902 		<< "\n"
1903 		<< "    gl_MeshVerticesNV[0].gl_Position = " << meshPvdPrefix << ".positions[0]; //vec4(-1.0, -1.0, 0.0, 1.0)\n"
1904 		<< "    gl_MeshVerticesNV[1].gl_Position = " << meshPvdPrefix << ".positions[1]; //vec4( 1.0, -1.0, 0.0, 1.0)\n"
1905 		<< "    gl_MeshVerticesNV[2].gl_Position = " << meshPvdPrefix << ".positions[2]; //vec4(-1.0,  1.0, 0.0, 1.0)\n"
1906 		<< "    gl_MeshVerticesNV[3].gl_Position = " << meshPvdPrefix << ".positions[3]; //vec4( 1.0,  1.0, 0.0, 1.0)\n"
1907 		<< "\n"
1908 		<< "    gl_MeshVerticesNV[0].gl_PointSize = " << meshPvdPrefix << ".pointSizes[0]; //1.0\n"
1909 		<< "    gl_MeshVerticesNV[1].gl_PointSize = " << meshPvdPrefix << ".pointSizes[1]; //1.0\n"
1910 		<< "    gl_MeshVerticesNV[2].gl_PointSize = " << meshPvdPrefix << ".pointSizes[2]; //1.0\n"
1911 		<< "    gl_MeshVerticesNV[3].gl_PointSize = " << meshPvdPrefix << ".pointSizes[3]; //1.0\n"
1912 		<< "\n"
1913 		<< "    // Remove geometry on the right side.\n"
1914 		<< "    gl_MeshVerticesNV[0].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[0]; // 1.0\n"
1915 		<< "    gl_MeshVerticesNV[1].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[1]; //-1.0\n"
1916 		<< "    gl_MeshVerticesNV[2].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[2]; // 1.0\n"
1917 		<< "    gl_MeshVerticesNV[3].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[3]; //-1.0\n"
1918 		<< "    \n"
1919 		<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
1920 		<< "    gl_PrimitiveIndicesNV[1] = 2;\n"
1921 		<< "    gl_PrimitiveIndicesNV[2] = 1;\n"
1922 		<< "\n"
1923 		<< "    gl_PrimitiveIndicesNV[3] = 2;\n"
1924 		<< "    gl_PrimitiveIndicesNV[4] = 3;\n"
1925 		<< "    gl_PrimitiveIndicesNV[5] = 1;\n"
1926 		<< "\n"
1927 		<< "    gl_MeshPrimitivesNV[0].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[0]; //1000\n"
1928 		<< "    gl_MeshPrimitivesNV[1].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[1]; //1001\n"
1929 		<< "\n"
1930 		<< "    gl_MeshPrimitivesNV[0].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[0]; //1\n"
1931 		<< "    gl_MeshPrimitivesNV[1].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[1]; //1\n"
1932 		<< "\n"
1933 		<< "    // Custom per-vertex attributes\n"
1934 		<< "    customAttribute1[0] = " << meshPvdPrefix << ".custom1[0]; //vec4(0.25, 0.5, 10.0, 3.0)\n"
1935 		<< "    customAttribute1[1] = " << meshPvdPrefix << ".custom1[1]; //vec4(0.25, 1.0, 20.0, 3.0)\n"
1936 		<< "    customAttribute1[2] = " << meshPvdPrefix << ".custom1[2]; //vec4( 0.5, 0.5, 20.0, 3.0)\n"
1937 		<< "    customAttribute1[3] = " << meshPvdPrefix << ".custom1[3]; //vec4( 0.5, 1.0, 10.0, 3.0)\n"
1938 		<< "\n"
1939 		<< "    customAttribute2[0] = " << meshPvdPrefix << ".custom2[0]; //1.0f\n"
1940 		<< "    customAttribute2[1] = " << meshPvdPrefix << ".custom2[1]; //1.0f\n"
1941 		<< "    customAttribute2[2] = " << meshPvdPrefix << ".custom2[2]; //2.0f\n"
1942 		<< "    customAttribute2[3] = " << meshPvdPrefix << ".custom2[3]; //2.0f\n"
1943 		<< "\n"
1944 		<< "    customAttribute3[0] = " << meshPvdPrefix << ".custom3[0]; //3\n"
1945 		<< "    customAttribute3[1] = " << meshPvdPrefix << ".custom3[1]; //3\n"
1946 		<< "    customAttribute3[2] = " << meshPvdPrefix << ".custom3[2]; //4\n"
1947 		<< "    customAttribute3[3] = " << meshPvdPrefix << ".custom3[3]; //4\n"
1948 		<< "\n"
1949 		<< "    // Custom per-primitive attributes.\n"
1950 		<< "    customAttribute4[0] = " << meshPpdPrefix << ".custom4[0]; //uvec4(100, 101, 102, 103)\n"
1951 		<< "    customAttribute4[1] = " << meshPpdPrefix << ".custom4[1]; //uvec4(200, 201, 202, 203)\n"
1952 		<< "\n"
1953 		<< "    customAttribute5[0] = " << meshPpdPrefix << ".custom5[0]; //6.0\n"
1954 		<< "    customAttribute5[1] = " << meshPpdPrefix << ".custom5[1]; //7.0\n"
1955 		<< "}\n"
1956 		;
1957 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
1958 
1959 	if (taskShader)
1960 	{
1961 		std::ostringstream task;
1962 		task
1963 			<< "#version 450\n"
1964 			<< "#extension GL_NV_mesh_shader : enable\n"
1965 			<< "\n"
1966 			<< "out " << taskDataDecl
1967 			<< bindingsDecl
1968 			<< "void main ()\n"
1969 			<< "{\n"
1970 			<< "    gl_TaskCountNV = " << m_params->meshCount << ";\n"
1971 			<< "\n"
1972 			<< "    td.positions[0] = pvd.positions[0];\n"
1973 			<< "    td.positions[1] = pvd.positions[1];\n"
1974 			<< "    td.positions[2] = pvd.positions[2];\n"
1975 			<< "    td.positions[3] = pvd.positions[3];\n"
1976 			<< "\n"
1977 			<< "    td.pointSizes[0] = pvd.pointSizes[0];\n"
1978 			<< "    td.pointSizes[1] = pvd.pointSizes[1];\n"
1979 			<< "    td.pointSizes[2] = pvd.pointSizes[2];\n"
1980 			<< "    td.pointSizes[3] = pvd.pointSizes[3];\n"
1981 			<< "\n"
1982 			<< "    td.clipDistances[0] = pvd.clipDistances[0];\n"
1983 			<< "    td.clipDistances[1] = pvd.clipDistances[1];\n"
1984 			<< "    td.clipDistances[2] = pvd.clipDistances[2];\n"
1985 			<< "    td.clipDistances[3] = pvd.clipDistances[3];\n"
1986 			<< "\n"
1987 			<< "    td.custom1[0] = pvd.custom1[0];\n"
1988 			<< "    td.custom1[1] = pvd.custom1[1];\n"
1989 			<< "    td.custom1[2] = pvd.custom1[2];\n"
1990 			<< "    td.custom1[3] = pvd.custom1[3];\n"
1991 			<< "\n"
1992 			<< "    td.custom2[0] = pvd.custom2[0];\n"
1993 			<< "    td.custom2[1] = pvd.custom2[1];\n"
1994 			<< "    td.custom2[2] = pvd.custom2[2];\n"
1995 			<< "    td.custom2[3] = pvd.custom2[3];\n"
1996 			<< "\n"
1997 			<< "    td.custom3[0] = pvd.custom3[0];\n"
1998 			<< "    td.custom3[1] = pvd.custom3[1];\n"
1999 			<< "    td.custom3[2] = pvd.custom3[2];\n"
2000 			<< "    td.custom3[3] = pvd.custom3[3];\n"
2001 			<< "\n"
2002 			<< "    td.primitiveIds[0] = ppd.primitiveIds[0];\n"
2003 			<< "    td.primitiveIds[1] = ppd.primitiveIds[1];\n"
2004 			<< "\n"
2005 			<< "    td.viewportIndices[0] = ppd.viewportIndices[0];\n"
2006 			<< "    td.viewportIndices[1] = ppd.viewportIndices[1];\n"
2007 			<< "\n"
2008 			<< "    td.custom4[0] = ppd.custom4[0];\n"
2009 			<< "    td.custom4[1] = ppd.custom4[1];\n"
2010 			<< "\n"
2011 			<< "    td.custom5[0] = ppd.custom5[0];\n"
2012 			<< "    td.custom5[1] = ppd.custom5[1];\n"
2013 			<< "}\n"
2014 			;
2015 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
2016 	}
2017 }
2018 
generateReferenceLevel()2019 void CustomAttributesInstance::generateReferenceLevel ()
2020 {
2021 	const auto format		= getOutputFormat();
2022 	const auto tcuFormat	= mapVkFormat(format);
2023 
2024 	const auto iWidth		= static_cast<int>(m_params->width);
2025 	const auto iHeight		= static_cast<int>(m_params->height);
2026 
2027 	const auto halfWidth	= iWidth / 2;
2028 	const auto halfHeight	= iHeight / 2;
2029 
2030 	m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
2031 
2032 	const auto access		= m_referenceLevel->getAccess();
2033 	const auto clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
2034 	const auto blueColor	= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2035 
2036 	tcu::clear(access, clearColor);
2037 
2038 	// Fill the top left quarter.
2039 	for (int y = 0; y < halfWidth; ++y)
2040 	for (int x = 0; x < halfHeight; ++x)
2041 	{
2042 		access.setPixel(blueColor, x, y);
2043 	}
2044 }
2045 
iterate()2046 tcu::TestStatus CustomAttributesInstance::iterate ()
2047 {
2048 	struct PerVertexData
2049 	{
2050 		tcu::Vec4	positions[4];
2051 		float		pointSizes[4];
2052 		float		clipDistances[4];
2053 		tcu::Vec4	custom1[4];
2054 		float		custom2[4];
2055 		int32_t		custom3[4];
2056 	};
2057 
2058 	struct PerPrimitiveData
2059 	{
2060 		// Note some of these are declared as vectors to match the std140 layout.
2061 		tcu::IVec4	primitiveIds[2];
2062 		tcu::IVec4	viewportIndices[2];
2063 		tcu::UVec4	custom4[2];
2064 		tcu::Vec4	custom5[2];
2065 	};
2066 
2067 	const auto&		vkd			= m_context.getDeviceInterface();
2068 	const auto		device		= m_context.getDevice();
2069 	auto&			alloc		= m_context.getDefaultAllocator();
2070 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
2071 	const auto		queue		= m_context.getUniversalQueue();
2072 
2073 	const auto		imageFormat	= getOutputFormat();
2074 	const auto		tcuFormat	= mapVkFormat(imageFormat);
2075 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
2076 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2077 
2078 	const auto&		binaries	= m_context.getBinaryCollection();
2079 	const auto		hasTask		= binaries.contains("task");
2080 	const auto		bufStages	= (hasTask ? VK_SHADER_STAGE_TASK_BIT_NV : VK_SHADER_STAGE_MESH_BIT_NV);
2081 
2082 	const VkImageCreateInfo colorBufferInfo =
2083 	{
2084 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2085 		nullptr,								//	const void*				pNext;
2086 		0u,										//	VkImageCreateFlags		flags;
2087 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2088 		imageFormat,							//	VkFormat				format;
2089 		imageExtent,							//	VkExtent3D				extent;
2090 		1u,										//	uint32_t				mipLevels;
2091 		1u,										//	uint32_t				arrayLayers;
2092 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2093 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2094 		imageUsage,								//	VkImageUsageFlags		usage;
2095 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2096 		0u,										//	uint32_t				queueFamilyIndexCount;
2097 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2098 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2099 	};
2100 
2101 	// Create color image and view.
2102 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
2103 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2104 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2105 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2106 
2107 	// Create a memory buffer for verification.
2108 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
2109 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2110 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
2111 
2112 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
2113 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
2114 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
2115 
2116 	// This needs to match what the fragment shader will expect.
2117 	const PerVertexData perVertexData =
2118 	{
2119 		//	tcu::Vec4	positions[4];
2120 		{
2121 			tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2122 			tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
2123 			tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
2124 			tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
2125 		},
2126 		//	float		pointSizes[4];
2127 		{ 1.0f, 1.0f, 1.0f, 1.0f, },
2128 		//	float		clipDistances[4];
2129 		{
2130 			1.0f,
2131 			-1.0f,
2132 			1.0f,
2133 			-1.0f,
2134 		},
2135 		//	tcu::Vec4	custom1[4];
2136 		{
2137 			tcu::Vec4(0.25, 0.5, 10.0, 3.0),
2138 			tcu::Vec4(0.25, 1.0, 20.0, 3.0),
2139 			tcu::Vec4( 0.5, 0.5, 20.0, 3.0),
2140 			tcu::Vec4( 0.5, 1.0, 10.0, 3.0),
2141 		},
2142 		//	float		custom2[4];
2143 		{ 1.0f, 1.0f, 2.0f, 2.0f, },
2144 		//	int32_t		custom3[4];
2145 		{ 3, 3, 4, 4 },
2146 	};
2147 
2148 	// This needs to match what the fragment shader will expect. Reminder: some of these are declared as gvec4 to match the std140
2149 	// layout, but only the first component is actually used.
2150 	const PerPrimitiveData perPrimitiveData =
2151 	{
2152 		//	int			primitiveIds[2];
2153 		{
2154 			tcu::IVec4(1000, 0, 0, 0),
2155 			tcu::IVec4(1001, 0, 0, 0),
2156 		},
2157 		//	int			viewportIndices[2];
2158 		{
2159 			tcu::IVec4(1, 0, 0, 0),
2160 			tcu::IVec4(1, 0, 0, 0),
2161 		},
2162 		//	uvec4		custom4[2];
2163 		{
2164 			tcu::UVec4(100u, 101u, 102u, 103u),
2165 			tcu::UVec4(200u, 201u, 202u, 203u),
2166 		},
2167 		//	float		custom5[2];
2168 		{
2169 			tcu::Vec4(6.0f, 0.0f, 0.0f, 0.0f),
2170 			tcu::Vec4(7.0f, 0.0f, 0.0f, 0.0f),
2171 		},
2172 	};
2173 
2174 	// Create and fill buffers with this data.
2175 	const auto			pvdSize		= static_cast<VkDeviceSize>(sizeof(perVertexData));
2176 	const auto			pvdInfo		= makeBufferCreateInfo(pvdSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2177 	BufferWithMemory	pvdData		(vkd, device, alloc, pvdInfo, MemoryRequirement::HostVisible);
2178 	auto&				pvdAlloc	= pvdData.getAllocation();
2179 	void*				pvdPtr		= pvdAlloc.getHostPtr();
2180 
2181 	const auto			ppdSize		= static_cast<VkDeviceSize>(sizeof(perPrimitiveData));
2182 	const auto			ppdInfo		= makeBufferCreateInfo(ppdSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
2183 	BufferWithMemory	ppdData		(vkd, device, alloc, ppdInfo, MemoryRequirement::HostVisible);
2184 	auto&				ppdAlloc	= ppdData.getAllocation();
2185 	void*				ppdPtr		= ppdAlloc.getHostPtr();
2186 
2187 	deMemcpy(pvdPtr, &perVertexData, sizeof(perVertexData));
2188 	deMemcpy(ppdPtr, &perPrimitiveData, sizeof(perPrimitiveData));
2189 
2190 	flushAlloc(vkd, device, pvdAlloc);
2191 	flushAlloc(vkd, device, ppdAlloc);
2192 
2193 	// Descriptor set layout.
2194 	DescriptorSetLayoutBuilder setLayoutBuilder;
2195 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bufStages);
2196 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bufStages);
2197 	const auto setLayout = setLayoutBuilder.build(vkd, device);
2198 
2199 	// Create and update descriptor set.
2200 	DescriptorPoolBuilder descriptorPoolBuilder;
2201 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2202 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
2203 	const auto descriptorPool	= descriptorPoolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2204 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2205 
2206 	DescriptorSetUpdateBuilder updateBuilder;
2207 	const auto storageBufferInfo = makeDescriptorBufferInfo(pvdData.get(), 0ull, pvdSize);
2208 	const auto uniformBufferInfo = makeDescriptorBufferInfo(ppdData.get(), 0ull, ppdSize);
2209 	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
2210 	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo);
2211 	updateBuilder.update(vkd, device);
2212 
2213 	// Pipeline layout.
2214 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2215 
2216 	// Shader modules.
2217 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
2218 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
2219 
2220 	Move<VkShaderModule> taskShader;
2221 	if (hasTask)
2222 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
2223 
2224 	// Render pass.
2225 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2226 
2227 	// Framebuffer.
2228 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
2229 
2230 	// Viewport and scissor.
2231 	const auto						topHalf		= makeViewport(imageExtent.width, imageExtent.height / 2u);
2232 	const std::vector<VkViewport>	viewports	{ makeViewport(imageExtent), topHalf };
2233 	const std::vector<VkRect2D>		scissors	(2u, makeRect2D(imageExtent));
2234 
2235 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2236 		taskShader.get(), meshShader.get(), fragShader.get(),
2237 		renderPass.get(), viewports, scissors);
2238 
2239 	// Command pool and buffer.
2240 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2241 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2242 	const auto cmdBuffer	= cmdBufferPtr.get();
2243 
2244 	beginCommandBuffer(vkd, cmdBuffer);
2245 
2246 	// Run pipeline.
2247 	const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
2248 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2249 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2250 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2251 	vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
2252 	endRenderPass(vkd, cmdBuffer);
2253 
2254 	// Copy color buffer to verification buffer.
2255 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2256 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
2257 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
2258 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
2259 
2260 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
2261 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
2262 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
2263 
2264 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
2265 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2266 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
2267 
2268 	endCommandBuffer(vkd, cmdBuffer);
2269 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2270 
2271 	// Generate reference image and compare results.
2272 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
2273 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
2274 
2275 	generateReferenceLevel();
2276 	invalidateAlloc(vkd, device, verificationBufferAlloc);
2277 	if (!verifyResult(verificationAccess))
2278 		TCU_FAIL("Result does not match reference; check log for details");
2279 
2280 	return tcu::TestStatus::pass("Pass");
2281 }
2282 
2283 // Tests that use push constants in the new stages.
2284 class PushConstantCase : public MeshShaderMiscCase
2285 {
2286 public:
PushConstantCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsPtr params)2287 					PushConstantCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
2288 						: MeshShaderMiscCase (testCtx, name, description, std::move(params))
2289 					{}
2290 
2291 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
2292 	TestInstance*	createInstance			(Context& context) const override;
2293 };
2294 
2295 class PushConstantInstance : public MeshShaderMiscInstance
2296 {
2297 public:
PushConstantInstance(Context & context,const MiscTestParams * params)2298 	PushConstantInstance (Context& context, const MiscTestParams* params)
2299 		: MeshShaderMiscInstance (context, params)
2300 	{}
2301 
2302 	void			generateReferenceLevel	() override;
2303 	tcu::TestStatus	iterate					() override;
2304 };
2305 
createInstance(Context & context) const2306 TestInstance* PushConstantCase::createInstance (Context& context) const
2307 {
2308 	return new PushConstantInstance(context, m_params.get());
2309 }
2310 
generateReferenceLevel()2311 void PushConstantInstance::generateReferenceLevel ()
2312 {
2313 	generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
2314 }
2315 
initPrograms(vk::SourceCollections & programCollection) const2316 void PushConstantCase::initPrograms (vk::SourceCollections& programCollection) const
2317 {
2318 	const auto useTaskShader	= m_params->needsTaskShader();
2319 	const auto pcNumFloats		= (useTaskShader ? 2u : 4u);
2320 
2321 	std::ostringstream pushConstantStream;
2322 	pushConstantStream
2323 		<< "layout (push_constant, std430) uniform PushConstantBlock {\n"
2324 		<< "    layout (offset=${PCOFFSET}) float values[" << pcNumFloats << "];\n"
2325 		<< "} pc;\n"
2326 		<< "\n"
2327 		;
2328 	const tcu::StringTemplate pushConstantsTemplate (pushConstantStream.str());
2329 	using TemplateMap = std::map<std::string, std::string>;
2330 
2331 	std::ostringstream taskDataStream;
2332 	taskDataStream
2333 		<< "taskNV TaskData {\n"
2334 		<< "    float values[2];\n"
2335 		<< "} td;\n"
2336 		<< "\n"
2337 		;
2338 	const auto taskDataDecl = taskDataStream.str();
2339 
2340 	if (useTaskShader)
2341 	{
2342 		TemplateMap taskMap;
2343 		taskMap["PCOFFSET"] = std::to_string(2u * sizeof(float));
2344 
2345 		std::ostringstream task;
2346 		task
2347 			<< "#version 450\n"
2348 			<< "#extension GL_NV_mesh_shader : enable\n"
2349 			<< "\n"
2350 			<< "layout(local_size_x=1) in;\n"
2351 			<< "\n"
2352 			<< "out " << taskDataDecl
2353 			<< pushConstantsTemplate.specialize(taskMap)
2354 			<< "void main ()\n"
2355 			<< "{\n"
2356 			<< "    gl_TaskCountNV = " << m_params->meshCount << ";\n"
2357 			<< "\n"
2358 			<< "    td.values[0] = pc.values[0];\n"
2359 			<< "    td.values[1] = pc.values[1];\n"
2360 			<< "}\n"
2361 			;
2362 		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
2363 	}
2364 
2365 	{
2366 		const std::string blue	= (useTaskShader ? "td.values[0] + pc.values[0]" : "pc.values[0] + pc.values[2]");
2367 		const std::string alpha	= (useTaskShader ? "td.values[1] + pc.values[1]" : "pc.values[1] + pc.values[3]");
2368 
2369 		TemplateMap meshMap;
2370 		meshMap["PCOFFSET"] = "0";
2371 
2372 		std::ostringstream mesh;
2373 		mesh
2374 			<< "#version 450\n"
2375 			<< "#extension GL_NV_mesh_shader : enable\n"
2376 			<< "\n"
2377 			<< "layout(local_size_x=1) in;\n"
2378 			<< "layout(triangles) out;\n"
2379 			<< "layout(max_vertices=3, max_primitives=1) out;\n"
2380 			<< "\n"
2381 			<< "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
2382 			<< "\n"
2383 			<< pushConstantsTemplate.specialize(meshMap)
2384 			<< (useTaskShader ? "in " + taskDataDecl : "")
2385 			<< "void main ()\n"
2386 			<< "{\n"
2387 			<< "    gl_PrimitiveCountNV = 1;\n"
2388 			<< "\n"
2389 			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
2390 			<< "    gl_MeshVerticesNV[1].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
2391 			<< "    gl_MeshVerticesNV[2].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
2392 			<< "\n"
2393 			<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
2394 			<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
2395 			<< "    gl_PrimitiveIndicesNV[2] = 2;\n"
2396 			<< "\n"
2397 			<< "    triangleColor[0] = vec4(0.0, 0.0, " << blue << ", " << alpha << ");\n"
2398 			<< "}\n"
2399 			;
2400 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
2401 	}
2402 
2403 	// Add default fragment shader.
2404 	MeshShaderMiscCase::initPrograms(programCollection);
2405 }
2406 
iterate()2407 tcu::TestStatus PushConstantInstance::iterate ()
2408 {
2409 	const auto&		vkd			= m_context.getDeviceInterface();
2410 	const auto		device		= m_context.getDevice();
2411 	auto&			alloc		= m_context.getDefaultAllocator();
2412 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
2413 	const auto		queue		= m_context.getUniversalQueue();
2414 
2415 	const auto		imageFormat	= getOutputFormat();
2416 	const auto		tcuFormat	= mapVkFormat(imageFormat);
2417 	const auto		imageExtent	= makeExtent3D(m_params->width, m_params->height, 1u);
2418 	const auto		imageUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2419 
2420 	const auto&		binaries	= m_context.getBinaryCollection();
2421 	const auto		hasTask		= binaries.contains("task");
2422 
2423 	const VkImageCreateInfo colorBufferInfo =
2424 	{
2425 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2426 		nullptr,								//	const void*				pNext;
2427 		0u,										//	VkImageCreateFlags		flags;
2428 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2429 		imageFormat,							//	VkFormat				format;
2430 		imageExtent,							//	VkExtent3D				extent;
2431 		1u,										//	uint32_t				mipLevels;
2432 		1u,										//	uint32_t				arrayLayers;
2433 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2434 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2435 		imageUsage,								//	VkImageUsageFlags		usage;
2436 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2437 		0u,										//	uint32_t				queueFamilyIndexCount;
2438 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2439 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2440 	};
2441 
2442 	// Create color image and view.
2443 	ImageWithMemory	colorImage	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
2444 	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2445 	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2446 	const auto		colorView	= makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2447 
2448 	// Create a memory buffer for verification.
2449 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
2450 	const auto			verificationBufferUsage	= (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2451 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
2452 
2453 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
2454 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
2455 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
2456 
2457 	// Push constant ranges.
2458 	std::vector<float> pcData { 0.25f, 0.25f, 0.75f, 0.75f };
2459 	const auto pcSize		= static_cast<uint32_t>(de::dataSize(pcData));
2460 	const auto pcHalfSize	= pcSize / 2u;
2461 
2462 	std::vector<VkPushConstantRange> pcRanges;
2463 	if (hasTask)
2464 	{
2465 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_NV, 0u, pcHalfSize));
2466 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_TASK_BIT_NV, pcHalfSize, pcHalfSize));
2467 	}
2468 	else
2469 	{
2470 		pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_NV, 0u, pcSize));
2471 	}
2472 
2473 	// Pipeline layout.
2474 	const auto pipelineLayout = makePipelineLayout(vkd, device, 0u, nullptr, static_cast<uint32_t>(pcRanges.size()), de::dataOrNull(pcRanges));
2475 
2476 	// Shader modules.
2477 	const auto	meshShader	= createShaderModule(vkd, device, binaries.get("mesh"));
2478 	const auto	fragShader	= createShaderModule(vkd, device, binaries.get("frag"));
2479 
2480 	Move<VkShaderModule> taskShader;
2481 	if (hasTask)
2482 		taskShader = createShaderModule(vkd, device, binaries.get("task"));
2483 
2484 	// Render pass.
2485 	const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2486 
2487 	// Framebuffer.
2488 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
2489 
2490 	// Viewport and scissor.
2491 	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
2492 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
2493 
2494 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2495 		taskShader.get(), meshShader.get(), fragShader.get(),
2496 		renderPass.get(), viewports, scissors);
2497 
2498 	// Command pool and buffer.
2499 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2500 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2501 	const auto cmdBuffer	= cmdBufferPtr.get();
2502 
2503 	beginCommandBuffer(vkd, cmdBuffer);
2504 
2505 	// Run pipeline.
2506 	const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
2507 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2508 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2509 	for (const auto& range : pcRanges)
2510 		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), range.stageFlags, range.offset, range.size, reinterpret_cast<const char*>(pcData.data()) + range.offset);
2511 	vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
2512 	endRenderPass(vkd, cmdBuffer);
2513 
2514 	// Copy color buffer to verification buffer.
2515 	const auto colorAccess		= (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2516 	const auto transferRead		= VK_ACCESS_TRANSFER_READ_BIT;
2517 	const auto transferWrite	= VK_ACCESS_TRANSFER_WRITE_BIT;
2518 	const auto hostRead			= VK_ACCESS_HOST_READ_BIT;
2519 
2520 	const auto preCopyBarrier	= makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
2521 	const auto postCopyBarrier	= makeMemoryBarrier(transferWrite, hostRead);
2522 	const auto copyRegion		= makeBufferImageCopy(imageExtent, colorSRL);
2523 
2524 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
2525 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2526 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
2527 
2528 	endCommandBuffer(vkd, cmdBuffer);
2529 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2530 
2531 	// Generate reference image and compare results.
2532 	const tcu::IVec3					iExtent				(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
2533 	const tcu::ConstPixelBufferAccess	verificationAccess	(tcuFormat, iExtent, verificationBufferData);
2534 
2535 	generateReferenceLevel();
2536 	invalidateAlloc(vkd, device, verificationBufferAlloc);
2537 	if (!verifyResult(verificationAccess))
2538 		TCU_FAIL("Result does not match reference; check log for details");
2539 
2540 	return tcu::TestStatus::pass("Pass");
2541 }
2542 
2543 }
2544 
createMeshShaderMiscTests(tcu::TestContext & testCtx)2545 tcu::TestCaseGroup* createMeshShaderMiscTests (tcu::TestContext& testCtx)
2546 {
2547 	GroupPtr miscTests (new tcu::TestCaseGroup(testCtx, "misc", "Mesh Shader Misc Tests"));
2548 
2549 	{
2550 		ParamsPtr paramsPtr (new MiscTestParams);
2551 
2552 		paramsPtr->taskCount	= tcu::just(2u);
2553 		paramsPtr->meshCount	= 2u;
2554 		paramsPtr->width		= 8u;
2555 		paramsPtr->height		= 8u;
2556 
2557 		miscTests->addChild(new ComplexTaskDataCase(testCtx, "complex_task_data", "Pass a complex structure from the task to the mesh shader", std::move(paramsPtr)));
2558 	}
2559 
2560 	{
2561 		ParamsPtr paramsPtr (new MiscTestParams);
2562 
2563 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2564 		paramsPtr->meshCount	= 1u;
2565 		paramsPtr->width		= 5u;	// Use an odd value so there's a pixel in the exact center.
2566 		paramsPtr->height		= 7u;	// Idem.
2567 
2568 		miscTests->addChild(new SinglePointCase(testCtx, "single_point", "Draw a single point", std::move(paramsPtr)));
2569 	}
2570 
2571 	{
2572 		ParamsPtr paramsPtr (new MiscTestParams);
2573 
2574 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2575 		paramsPtr->meshCount	= 1u;
2576 		paramsPtr->width		= 8u;
2577 		paramsPtr->height		= 5u;	// Use an odd value so there's a center line.
2578 
2579 		miscTests->addChild(new SingleLineCase(testCtx, "single_line", "Draw a single line", std::move(paramsPtr)));
2580 	}
2581 
2582 	{
2583 		ParamsPtr paramsPtr (new MiscTestParams);
2584 
2585 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2586 		paramsPtr->meshCount	= 1u;
2587 		paramsPtr->width		= 5u;	// Use an odd value so there's a pixel in the exact center.
2588 		paramsPtr->height		= 7u;	// Idem.
2589 
2590 		miscTests->addChild(new SingleTriangleCase(testCtx, "single_triangle", "Draw a single triangle", std::move(paramsPtr)));
2591 	}
2592 
2593 	{
2594 		ParamsPtr paramsPtr (new MiscTestParams);
2595 
2596 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2597 		paramsPtr->meshCount	= 1u;
2598 		paramsPtr->width		= 16u;
2599 		paramsPtr->height		= 16u;
2600 
2601 		miscTests->addChild(new MaxPointsCase(testCtx, "max_points", "Draw the maximum number of points", std::move(paramsPtr)));
2602 	}
2603 
2604 	{
2605 		ParamsPtr paramsPtr (new MiscTestParams);
2606 
2607 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2608 		paramsPtr->meshCount	= 1u;
2609 		paramsPtr->width		= 1u;
2610 		paramsPtr->height		= 1020u;
2611 
2612 		miscTests->addChild(new MaxLinesCase(testCtx, "max_lines", "Draw the maximum number of lines", std::move(paramsPtr)));
2613 	}
2614 
2615 	{
2616 		ParamsPtr paramsPtr (new MiscTestParams);
2617 
2618 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2619 		paramsPtr->meshCount	= 1u;
2620 		paramsPtr->width		= 512u;
2621 		paramsPtr->height		= 512u;
2622 
2623 		miscTests->addChild(new MaxTrianglesCase(testCtx, "max_triangles", "Draw the maximum number of triangles", std::move(paramsPtr)));
2624 	}
2625 
2626 	{
2627 		ParamsPtr paramsPtr (new MiscTestParams);
2628 
2629 		paramsPtr->taskCount	= tcu::just(65535u);
2630 		paramsPtr->meshCount	= 1u;
2631 		paramsPtr->width		= 1360u;
2632 		paramsPtr->height		= 1542u;
2633 
2634 		miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_task_work_groups", "Generate a large number of task work groups", std::move(paramsPtr)));
2635 	}
2636 
2637 	{
2638 		ParamsPtr paramsPtr (new MiscTestParams);
2639 
2640 		paramsPtr->taskCount	= tcu::nothing<uint32_t>();
2641 		paramsPtr->meshCount	= 65535u;
2642 		paramsPtr->width		= 1360u;
2643 		paramsPtr->height		= 1542u;
2644 
2645 		miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_mesh_work_groups", "Generate a large number of mesh work groups", std::move(paramsPtr)));
2646 	}
2647 
2648 	{
2649 		ParamsPtr paramsPtr (new MiscTestParams);
2650 
2651 		paramsPtr->taskCount	= tcu::just(512u);
2652 		paramsPtr->meshCount	= 512u;
2653 		paramsPtr->width		= 4096u;
2654 		paramsPtr->height		= 2048u;
2655 
2656 		miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_task_mesh_work_groups", "Generate a large number of task and mesh work groups", std::move(paramsPtr)));
2657 	}
2658 
2659 	{
2660 		const PrimitiveType types[] = {
2661 			PrimitiveType::POINTS,
2662 			PrimitiveType::LINES,
2663 			PrimitiveType::TRIANGLES,
2664 		};
2665 
2666 		for (int i = 0; i < 2; ++i)
2667 		{
2668 			const bool extraWrites = (i > 0);
2669 
2670 			for (const auto primType : types)
2671 			{
2672 				std::unique_ptr<NoPrimitivesParams> params (new NoPrimitivesParams);
2673 				params->taskCount		= (extraWrites ? tcu::just(1u) : tcu::nothing<uint32_t>());
2674 				params->meshCount		= 1u;
2675 				params->width			= 16u;
2676 				params->height			= 16u;
2677 				params->primitiveType	= primType;
2678 
2679 				ParamsPtr			paramsPtr	(params.release());
2680 				const auto			primName	= primitiveTypeName(primType);
2681 				const std::string	name		= "no_" + primName + (extraWrites ? "_extra_writes" : "");
2682 				const std::string	desc		= "Run a pipeline that generates no " + primName + (extraWrites ? " but generates primitive data" : "");
2683 
2684 				miscTests->addChild(extraWrites
2685 					? (new NoPrimitivesExtraWritesCase(testCtx, name, desc, std::move(paramsPtr)))
2686 					: (new NoPrimitivesCase(testCtx, name, desc, std::move(paramsPtr))));
2687 			}
2688 		}
2689 	}
2690 
2691 	{
2692 		for (int i = 0; i < 2; ++i)
2693 		{
2694 			const bool useTaskShader = (i == 0);
2695 
2696 			ParamsPtr paramsPtr (new MiscTestParams);
2697 
2698 			paramsPtr->taskCount		= (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
2699 			paramsPtr->meshCount		= 1u;
2700 			paramsPtr->width			= 1u;
2701 			paramsPtr->height			= 1u;
2702 
2703 			const std::string shader	= (useTaskShader ? "task" : "mesh");
2704 			const std::string name		= "barrier_in_" + shader;
2705 			const std::string desc		= "Use a control barrier in the " + shader + " shader";
2706 
2707 			miscTests->addChild(new SimpleBarrierCase(testCtx, name, desc, std::move(paramsPtr)));
2708 		}
2709 	}
2710 
2711 	{
2712 		const struct
2713 		{
2714 			MemoryBarrierType	memBarrierType;
2715 			std::string			caseName;
2716 		} barrierTypes[] =
2717 		{
2718 			{ MemoryBarrierType::SHARED,	"memory_barrier_shared"	},
2719 			{ MemoryBarrierType::GROUP,		"group_memory_barrier"	},
2720 		};
2721 
2722 		for (const auto& barrierCase : barrierTypes)
2723 		{
2724 			for (int i = 0; i < 2; ++i)
2725 			{
2726 				const bool useTaskShader = (i == 0);
2727 
2728 				std::unique_ptr<MemoryBarrierParams> paramsPtr (new MemoryBarrierParams);
2729 
2730 				paramsPtr->taskCount		= (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
2731 				paramsPtr->meshCount		= 1u;
2732 				paramsPtr->width			= 1u;
2733 				paramsPtr->height			= 1u;
2734 				paramsPtr->memBarrierType	= barrierCase.memBarrierType;
2735 
2736 				const std::string shader	= (useTaskShader ? "task" : "mesh");
2737 				const std::string name		= barrierCase.caseName + "_in_" + shader;
2738 				const std::string desc		= "Use " + paramsPtr->glslFunc() + "() in the " + shader + " shader";
2739 
2740 				miscTests->addChild(new MemoryBarrierCase(testCtx, name, desc, std::move(paramsPtr)));
2741 			}
2742 		}
2743 	}
2744 
2745 	{
2746 		for (int i = 0; i < 2; ++i)
2747 		{
2748 			const bool useTaskShader	= (i > 0);
2749 			const auto name				= std::string("custom_attributes") + (useTaskShader ? "_and_task_shader" : "");
2750 			const auto desc				= std::string("Use several custom vertex and primitive attributes") + (useTaskShader ? " and also a task shader" : "");
2751 
2752 			ParamsPtr paramsPtr (new MiscTestParams);
2753 
2754 			paramsPtr->taskCount		= (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
2755 			paramsPtr->meshCount		= 1u;
2756 			paramsPtr->width			= 32u;
2757 			paramsPtr->height			= 32u;
2758 
2759 			miscTests->addChild(new CustomAttributesCase(testCtx, name, desc, std::move(paramsPtr)));
2760 		}
2761 	}
2762 
2763 	{
2764 		for (int i = 0; i < 2; ++i)
2765 		{
2766 			const bool useTaskShader	= (i > 0);
2767 			const auto name				= std::string("push_constant") + (useTaskShader ? "_and_task_shader" : "");
2768 			const auto desc				= std::string("Use push constants in the mesh shader stage") + (useTaskShader ? " and also in the task shader stage" : "");
2769 
2770 			ParamsPtr paramsPtr (new MiscTestParams);
2771 
2772 			paramsPtr->taskCount		= (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
2773 			paramsPtr->meshCount		= 1u;
2774 			paramsPtr->width			= 16u;
2775 			paramsPtr->height			= 16u;
2776 
2777 			miscTests->addChild(new PushConstantCase(testCtx, name, desc, std::move(paramsPtr)));
2778 		}
2779 	}
2780 
2781 	return miscTests.release();
2782 }
2783 
2784 } // MeshShader
2785 } // vkt
2786