• 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  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Mesh Shader Smoke Tests for VK_EXT_mesh_shader
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktMeshShaderSmokeTestsEXT.hpp"
28 #include "vktMeshShaderUtil.hpp"
29 #include "vktTestCase.hpp"
30 #include "vktTestCaseUtil.hpp"
31 
32 #include "vkBuilderUtil.hpp"
33 #include "vkImageWithMemory.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkPipelineConstructionUtil.hpp"
41 
42 #include "tcuImageCompare.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuTextureUtil.hpp"
45 
46 #include "deRandom.hpp"
47 
48 #include <utility>
49 #include <vector>
50 #include <string>
51 #include <sstream>
52 #include <set>
53 #include <memory>
54 
55 namespace vkt
56 {
57 namespace MeshShader
58 {
59 
60 namespace
61 {
62 
63 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
64 
65 using namespace vk;
66 
commonMeshFragShader()67 std::string commonMeshFragShader ()
68 {
69 	std::string frag =
70 		"#version 450\n"
71 		"#extension GL_EXT_mesh_shader : enable\n"
72 		"\n"
73 		"layout (location=0) in perprimitiveEXT vec4 triangleColor;\n"
74 		"layout (location=0) out vec4 outColor;\n"
75 		"\n"
76 		"void main ()\n"
77 		"{\n"
78 		"	outColor = triangleColor;\n"
79 		"}\n"
80 		;
81 	return frag;
82 }
83 
getClearColor()84 tcu::Vec4 getClearColor ()
85 {
86 	return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
87 }
88 
makeMeshGraphicsPipeline(GraphicsPipelineWrapper & maker,const PipelineLayoutWrapper & pipelineLayout,const ShaderWrapper taskShader,const ShaderWrapper meshShader,const ShaderWrapper fragShader,const VkRenderPass renderPass,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const uint32_t subpass=0u,const VkPipelineDepthStencilStateCreateInfo * depthStencilStateCreateInfo=nullptr,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateStateCreateInfo=nullptr)89 void makeMeshGraphicsPipeline (	GraphicsPipelineWrapper&							maker,
90 								const PipelineLayoutWrapper&						pipelineLayout,
91 								const ShaderWrapper									taskShader,
92 								const ShaderWrapper									meshShader,
93 								const ShaderWrapper									fragShader,
94 								const VkRenderPass									renderPass,
95 								const std::vector<VkViewport>&						viewports,
96 								const std::vector<VkRect2D>&						scissors,
97 								const uint32_t										subpass = 0u,
98 								const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo = nullptr,
99 								VkPipelineFragmentShadingRateStateCreateInfoKHR*	fragmentShadingRateStateCreateInfo = nullptr)
100 {
101 #ifndef CTS_USES_VULKANSC
102 	maker.setDefaultMultisampleState()
103 		 .setDefaultColorBlendState()
104 		 .setDefaultRasterizationState()
105 		 .setDefaultDepthStencilState()
106 		 .setupPreRasterizationMeshShaderState(viewports,
107 											   scissors,
108 											   pipelineLayout,
109 											   renderPass,
110 											   subpass,
111 											   taskShader,
112 											   meshShader,
113 											   nullptr,
114 											   nullptr,
115 											   nullptr,
116 											   fragmentShadingRateStateCreateInfo)
117 		 .setupFragmentShaderState(pipelineLayout,
118 								   renderPass,
119 								   subpass,
120 								   fragShader,
121 								   depthStencilStateCreateInfo)
122 		 .setupFragmentOutputState(renderPass, subpass)
123 		 .setMonolithicPipelineLayout(pipelineLayout)
124 		 .buildPipeline();
125 #else
126 	DE_ASSERT(false);
127 #endif // CTS_USES_VULKANSC
128 }
129 
130 struct MeshTriangleRendererParams
131 {
132 	PipelineConstructionType	constructionType;
133 	std::vector<tcu::Vec4>		vertexCoords;
134 	std::vector<uint32_t>		vertexIndices;
135 	uint32_t					taskCount;
136 	tcu::Vec4					expectedColor;
137 	bool						rasterizationDisabled;
138 
MeshTriangleRendererParamsvkt::MeshShader::__anon4a1cb0ed0111::MeshTriangleRendererParams139 	MeshTriangleRendererParams (PipelineConstructionType	constructionType_,
140 								std::vector<tcu::Vec4>		vertexCoords_,
141 								std::vector<uint32_t>		vertexIndices_,
142 								uint32_t					taskCount_,
143 								const tcu::Vec4&			expectedColor_,
144 								bool						rasterizationDisabled_ = false)
145 		: constructionType		(constructionType_)
146 		, vertexCoords			(std::move(vertexCoords_))
147 		, vertexIndices			(std::move(vertexIndices_))
148 		, taskCount				(taskCount_)
149 		, expectedColor			(expectedColor_)
150 		, rasterizationDisabled	(rasterizationDisabled_)
151 	{}
152 
MeshTriangleRendererParamsvkt::MeshShader::__anon4a1cb0ed0111::MeshTriangleRendererParams153 	MeshTriangleRendererParams (MeshTriangleRendererParams&& other)
154 		: MeshTriangleRendererParams (other.constructionType,
155 									  std::move(other.vertexCoords),
156 									  std::move(other.vertexIndices),
157 									  other.taskCount,
158 									  other.expectedColor,
159 									  other.rasterizationDisabled)
160 	{}
161 };
162 
163 class MeshOnlyTriangleCase : public vkt::TestCase
164 {
165 public:
MeshOnlyTriangleCase(tcu::TestContext & testCtx,const std::string & name,PipelineConstructionType constructionType,bool rasterizationDisabled=false)166 					MeshOnlyTriangleCase			(tcu::TestContext& testCtx, const std::string& name,
167 													 PipelineConstructionType constructionType, bool rasterizationDisabled = false)
168 						: vkt::TestCase				(testCtx, name)
169 						, m_constructionType		(constructionType)
170 						, m_rasterizationDisabled	(rasterizationDisabled)
171 						{}
~MeshOnlyTriangleCase(void)172 	virtual			~MeshOnlyTriangleCase	(void) {}
173 
174 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
175 	TestInstance*	createInstance			(Context& context) const override;
176 	void			checkSupport			(Context& context) const override;
177 
178 protected:
179 	const PipelineConstructionType	m_constructionType;
180 	const bool						m_rasterizationDisabled;
181 };
182 
183 class MeshTaskTriangleCase : public vkt::TestCase
184 {
185 public:
MeshTaskTriangleCase(tcu::TestContext & testCtx,const std::string & name,PipelineConstructionType constructionType)186 					MeshTaskTriangleCase	(tcu::TestContext& testCtx, const std::string& name, PipelineConstructionType constructionType)
187 						: vkt::TestCase			(testCtx, name)
188 						, m_constructionType	(constructionType)
189 						{}
~MeshTaskTriangleCase(void)190 	virtual			~MeshTaskTriangleCase	(void) {}
191 
192 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
193 	TestInstance*	createInstance			(Context& context) const override;
194 	void			checkSupport			(Context& context) const override;
195 
196 protected:
197 	const PipelineConstructionType m_constructionType;
198 };
199 
200 // Note: not actually task-only. The task shader will not emit mesh shader work groups.
201 class TaskOnlyTriangleCase : public vkt::TestCase
202 {
203 public:
TaskOnlyTriangleCase(tcu::TestContext & testCtx,const std::string & name,PipelineConstructionType constructionType)204 					TaskOnlyTriangleCase	(tcu::TestContext& testCtx, const std::string& name, PipelineConstructionType constructionType)
205 						: vkt::TestCase			(testCtx, name)
206 						, m_constructionType	(constructionType)
207 						{}
~TaskOnlyTriangleCase(void)208 	virtual			~TaskOnlyTriangleCase	(void) {}
209 
210 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
211 	TestInstance*	createInstance			(Context& context) const override;
212 	void			checkSupport			(Context& context) const override;
213 
214 protected:
215 	const PipelineConstructionType m_constructionType;
216 };
217 
218 class MeshTriangleRenderer : public vkt::TestInstance
219 {
220 public:
MeshTriangleRenderer(Context & context,MeshTriangleRendererParams params)221 						MeshTriangleRenderer	(Context& context, MeshTriangleRendererParams params) : vkt::TestInstance(context), m_params(std::move(params)) {}
~MeshTriangleRenderer(void)222 	virtual				~MeshTriangleRenderer	(void) {}
223 
224 	tcu::TestStatus		iterate					(void) override;
225 
226 protected:
227 	MeshTriangleRendererParams	m_params;
228 };
229 
checkSupport(Context & context) const230 void MeshOnlyTriangleCase::checkSupport (Context& context) const
231 {
232 	checkTaskMeshShaderSupportEXT(context, false, true);
233 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
234 }
235 
checkSupport(Context & context) const236 void MeshTaskTriangleCase::checkSupport (Context& context) const
237 {
238 	checkTaskMeshShaderSupportEXT(context, true, true);
239 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
240 }
241 
checkSupport(Context & context) const242 void TaskOnlyTriangleCase::checkSupport (Context& context) const
243 {
244 	checkTaskMeshShaderSupportEXT(context, true, true);
245 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
246 }
247 
initPrograms(SourceCollections & dst) const248 void MeshOnlyTriangleCase::initPrograms (SourceCollections& dst) const
249 {
250 	const auto buildOptions = getMinMeshEXTBuildOptions(dst.usedVulkanVersion);
251 
252 	std::ostringstream mesh;
253 	mesh
254 		<< "#version 450\n"
255 		<< "#extension GL_EXT_mesh_shader : enable\n"
256 		<< "\n"
257 		// We will actually output a single triangle and most invocations will do no work.
258 		<< "layout(local_size_x=8, local_size_y=4, local_size_z=4) in;\n"
259 		<< "layout(triangles) out;\n"
260 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
261 		<< "\n"
262 		// Unique vertex coordinates.
263 		<< "layout (set=0, binding=0) uniform CoordsBuffer {\n"
264 		<< "    vec4 coords[3];\n"
265 		<< "} cb;\n"
266 		// Unique vertex indices.
267 		<< "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
268 		<< "    uint indices[3];\n"
269 		<< "} ib;\n"
270 		<< "\n"
271 		// Triangle color.
272 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
273 		<< "\n"
274 		<< "void main ()\n"
275 		<< "{\n"
276 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
277 		<< "    triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
278 		<< "\n"
279 		<< "    const uint vertexIndex = gl_LocalInvocationIndex;\n"
280 		<< "    if (vertexIndex < 3u)\n"
281 		<< "    {\n"
282 		<< "        const uint coordsIndex = ib.indices[vertexIndex];\n"
283 		<< "        gl_MeshVerticesEXT[vertexIndex].gl_Position = cb.coords[coordsIndex];\n"
284 		<< "    }\n"
285 		<< "    if (vertexIndex == 0u)\n"
286 		<< "    {\n"
287 		<< "        gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
288 		<< "    }\n"
289 		<< "}\n"
290 		;
291 	dst.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
292 
293 	dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader()) << buildOptions;
294 }
295 
initPrograms(SourceCollections & dst) const296 void MeshTaskTriangleCase::initPrograms (SourceCollections& dst) const
297 {
298 	const auto buildOptions = getMinMeshEXTBuildOptions(dst.usedVulkanVersion);
299 
300 	std::string taskDataDecl =
301 		"struct TaskData {\n"
302 		"    uint triangleIndex;\n"
303 		"};\n"
304 		"taskPayloadSharedEXT TaskData td;\n"
305 		;
306 
307 	std::ostringstream task;
308 	task
309 		// Each work group spawns 1 task each (2 in total) and each task will draw 1 triangle.
310 		<< "#version 460\n"
311 		<< "#extension GL_EXT_mesh_shader : enable\n"
312 		<< "\n"
313 		<< "layout(local_size_x=8, local_size_y=4, local_size_z=4) in;\n"
314 		<< "\n"
315 		<< taskDataDecl
316 		<< "\n"
317 		<< "void main ()\n"
318 		<< "{\n"
319 		<< "    if (gl_LocalInvocationIndex == 0u)\n"
320 		<< "    {\n"
321 		<< "        td.triangleIndex = gl_WorkGroupID.x;\n"
322 		<< "    }\n"
323 		<< "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
324 		<< "}\n"
325 		;
326 		;
327 	dst.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
328 
329 	std::ostringstream mesh;
330 	mesh
331 		<< "#version 460\n"
332 		<< "#extension GL_EXT_mesh_shader : enable\n"
333 		<< "\n"
334 		// We will actually output a single triangle and most invocations will do no work.
335 		<< "layout(local_size_x=8, local_size_y=4, local_size_z=4) in;\n"
336 		<< "layout(triangles) out;\n"
337 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
338 		<< "\n"
339 		// Unique vertex coordinates.
340 		<< "layout (set=0, binding=0) uniform CoordsBuffer {\n"
341 		<< "    vec4 coords[4];\n"
342 		<< "} cb;\n"
343 		// Unique vertex indices.
344 		<< "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
345 		<< "    uint indices[6];\n"
346 		<< "} ib;\n"
347 		<< "\n"
348 		// Triangle color.
349 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
350 		<< "\n"
351 		<< taskDataDecl
352 		<< "\n"
353 		<< "void main ()\n"
354 		<< "{\n"
355 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
356 		<< "\n"
357 		// Each "active" invocation will copy one vertex.
358 		<< "    const uint triangleVertex = gl_LocalInvocationIndex;\n"
359 		<< "    const uint indexArrayPos  = td.triangleIndex * 3u + triangleVertex;\n"
360 		<< "\n"
361 		<< "    if (triangleVertex < 3u)\n"
362 		<< "    {\n"
363 		<< "        const uint coordsIndex = ib.indices[indexArrayPos];\n"
364 		// Copy vertex coordinates.
365 		<< "        gl_MeshVerticesEXT[triangleVertex].gl_Position = cb.coords[coordsIndex];\n"
366 		// Index renumbering: final indices will always be 0, 1, 2.
367 		<< "    }\n"
368 		<< "    if (triangleVertex == 0u)\n"
369 		<< "    {\n"
370 		<< "        gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
371 		<< "        triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
372 		<< "    }\n"
373 		<< "}\n"
374 		;
375 	dst.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
376 
377 	dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader()) << buildOptions;
378 }
379 
initPrograms(SourceCollections & dst) const380 void TaskOnlyTriangleCase::initPrograms (SourceCollections& dst) const
381 {
382 	const auto buildOptions = getMinMeshEXTBuildOptions(dst.usedVulkanVersion);
383 
384 	// The task shader does not spawn any mesh shader invocations.
385 	std::ostringstream task;
386 	task
387 		<< "#version 450\n"
388 		<< "#extension GL_EXT_mesh_shader : enable\n"
389 		<< "\n"
390 		<< "layout(local_size_x=1) in;\n"
391 		<< "\n"
392 		<< "void main ()\n"
393 		<< "{\n"
394 		<< "    EmitMeshTasksEXT(0u, 0u, 0u);\n"
395 		<< "}\n"
396 		;
397 	dst.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
398 
399 	// Same shader as the mesh only case, but it should not be launched.
400 	std::ostringstream mesh;
401 	mesh
402 		<< "#version 450\n"
403 		<< "#extension GL_EXT_mesh_shader : enable\n"
404 		<< "\n"
405 		// We will actually output a single triangle and most invocations will do no work.
406 		<< "layout(local_size_x=8, local_size_y=4, local_size_z=4) in;\n"
407 		<< "layout(triangles) out;\n"
408 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
409 		<< "\n"
410 		<< "layout (set=0, binding=0) uniform CoordsBuffer {\n"
411 		<< "    vec4 coords[3];\n"
412 		<< "} cb;\n"
413 		<< "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
414 		<< "    uint indices[3];\n"
415 		<< "} ib;\n"
416 		<< "\n"
417 		<< "layout (location=0) out perprimitiveEXT vec4 triangleColor[];\n"
418 		<< "\n"
419 		<< "void main ()\n"
420 		<< "{\n"
421 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
422 		<< "    triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
423 		<< "\n"
424 		<< "    const uint vertexIndex = gl_LocalInvocationIndex;\n"
425 		<< "    if (vertexIndex < 3u)\n"
426 		<< "    {\n"
427 		<< "        const uint coordsIndex = ib.indices[vertexIndex];\n"
428 		<< "        gl_MeshVerticesEXT[vertexIndex].gl_Position = cb.coords[coordsIndex];\n"
429 		<< "    }\n"
430 		<< "    if (vertexIndex == 0u)\n"
431 		<< "    {\n"
432 		<< "        gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
433 		<< "    }\n"
434 		<< "}\n"
435 		;
436 	dst.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
437 
438 	dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader()) << buildOptions;
439 }
440 
createInstance(Context & context) const441 TestInstance* MeshOnlyTriangleCase::createInstance (Context& context) const
442 {
443 	const std::vector<tcu::Vec4>	vertexCoords	=
444 	{
445 		tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
446 		tcu::Vec4(-1.0f,  3.0f, 0.0f, 1.0f),
447 		tcu::Vec4( 3.0f, -1.0f, 0.0f, 1.0f),
448 	};
449 	const std::vector<uint32_t>		vertexIndices	= { 0u, 1u, 2u };
450 	const auto						expectedColor	= (m_rasterizationDisabled ? getClearColor() : tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
451 	MeshTriangleRendererParams		params			(m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 1u, expectedColor, m_rasterizationDisabled);
452 
453 	return new MeshTriangleRenderer(context, std::move(params));
454 }
455 
createInstance(Context & context) const456 TestInstance* MeshTaskTriangleCase::createInstance (Context& context) const
457 {
458 	const std::vector<tcu::Vec4>	vertexCoords	=
459 	{
460 		tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
461 		tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
462 		tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
463 		tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
464 	};
465 	const std::vector<uint32_t>		vertexIndices	= { 2u, 0u, 1u, 1u, 3u, 2u };
466 	MeshTriangleRendererParams		params			(m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 2u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
467 
468 	return new MeshTriangleRenderer(context, std::move(params));
469 }
470 
createInstance(Context & context) const471 TestInstance* TaskOnlyTriangleCase::createInstance (Context& context) const
472 {
473 	const std::vector<tcu::Vec4>	vertexCoords	=
474 	{
475 		tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
476 		tcu::Vec4(-1.0f,  3.0f, 0.0f, 1.0f),
477 		tcu::Vec4( 3.0f, -1.0f, 0.0f, 1.0f),
478 	};
479 	const std::vector<uint32_t>		vertexIndices	= { 0u, 1u, 2u };
480 	// Note we expect the clear color.
481 	MeshTriangleRendererParams		params			(m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 1u, getClearColor());
482 
483 	return new MeshTriangleRenderer(context, std::move(params));
484 }
485 
iterate()486 tcu::TestStatus MeshTriangleRenderer::iterate ()
487 {
488 	const auto&		vki					= m_context.getInstanceInterface();
489 	const auto&		vkd					= m_context.getDeviceInterface();
490 	const auto		physicalDevice		= m_context.getPhysicalDevice();
491 	const auto		device				= m_context.getDevice();
492 	auto&			alloc				= m_context.getDefaultAllocator();
493 	const auto		qIndex				= m_context.getUniversalQueueFamilyIndex();
494 	const auto		queue				= m_context.getUniversalQueue();
495 
496 	const auto		vertexBufferStages	= VK_SHADER_STAGE_MESH_BIT_EXT;
497 	const auto		vertexBufferSize	= static_cast<VkDeviceSize>(de::dataSize(m_params.vertexCoords));
498 	const auto		vertexBufferUsage	= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
499 	const auto		vertexBufferLoc		= DescriptorSetUpdateBuilder::Location::binding(0u);
500 	const auto		vertexBufferType	= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
501 
502 	const auto		indexBufferStages	= VK_SHADER_STAGE_MESH_BIT_EXT;
503 	const auto		indexBufferSize		= static_cast<VkDeviceSize>(de::dataSize(m_params.vertexIndices));
504 	const auto		indexBufferUsage	= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
505 	const auto		indexBufferLoc		= DescriptorSetUpdateBuilder::Location::binding(1u);
506 	const auto		indexBufferType		= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
507 
508 	// Vertex buffer.
509 	const auto			vertexBufferInfo	= makeBufferCreateInfo(vertexBufferSize, vertexBufferUsage);
510 	BufferWithMemory	vertexBuffer		(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible);
511 	auto&				vertexBufferAlloc	= vertexBuffer.getAllocation();
512 	void*				vertexBufferDataPtr	= vertexBufferAlloc.getHostPtr();
513 
514 	deMemcpy(vertexBufferDataPtr, m_params.vertexCoords.data(), static_cast<size_t>(vertexBufferSize));
515 	flushAlloc(vkd, device, vertexBufferAlloc);
516 
517 	// Index buffer.
518 	const auto			indexBufferInfo		= makeBufferCreateInfo(indexBufferSize, indexBufferUsage);
519 	BufferWithMemory	indexBuffer			(vkd, device, alloc, indexBufferInfo, MemoryRequirement::HostVisible);
520 	auto&				indexBufferAlloc	= indexBuffer.getAllocation();
521 	void*				indexBufferDataPtr	= indexBufferAlloc.getHostPtr();
522 
523 	deMemcpy(indexBufferDataPtr, m_params.vertexIndices.data(), static_cast<size_t>(indexBufferSize));
524 	flushAlloc(vkd, device, indexBufferAlloc);
525 
526 	// Color buffer.
527 	const auto	colorBufferFormat	= VK_FORMAT_R8G8B8A8_UNORM;
528 	const auto	colorBufferExtent	= makeExtent3D(8u, 8u, 1u);
529 	const auto	colorBufferUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
530 
531 	const VkImageCreateInfo colorBufferInfo =
532 	{
533 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
534 		nullptr,								//	const void*				pNext;
535 		0u,										//	VkImageCreateFlags		flags;
536 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
537 		colorBufferFormat,						//	VkFormat				format;
538 		colorBufferExtent,						//	VkExtent3D				extent;
539 		1u,										//	uint32_t				mipLevels;
540 		1u,										//	uint32_t				arrayLayers;
541 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
542 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
543 		colorBufferUsage,						//	VkImageUsageFlags		usage;
544 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
545 		0u,										//	uint32_t				queueFamilyIndexCount;
546 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
547 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
548 	};
549 	ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
550 
551 	const auto colorSRR			= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
552 	const auto colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorBufferFormat, colorSRR);
553 
554 	// Render pass.
555 	const auto renderPass = makeRenderPass(vkd, device, colorBufferFormat);
556 
557 	// Framebuffer.
558 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorBufferExtent.width, colorBufferExtent.height);
559 
560 	// Set layout.
561 	DescriptorSetLayoutBuilder layoutBuilder;
562 	layoutBuilder.addSingleBinding(vertexBufferType, vertexBufferStages);
563 	layoutBuilder.addSingleBinding(indexBufferType, indexBufferStages);
564 	const auto setLayout = layoutBuilder.build(vkd, device);
565 
566 	// Descriptor pool.
567 	DescriptorPoolBuilder poolBuilder;
568 	poolBuilder.addType(vertexBufferType);
569 	poolBuilder.addType(indexBufferType);
570 	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
571 
572 	// Descriptor set.
573 	const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
574 
575 	// Update descriptor set.
576 	DescriptorSetUpdateBuilder updateBuilder;
577 	const auto vertexBufferDescInfo	= makeDescriptorBufferInfo(vertexBuffer.get(), 0ull, vertexBufferSize);
578 	const auto indexBufferDescInfo	= makeDescriptorBufferInfo(indexBuffer.get(), 0ull, indexBufferSize);
579 	updateBuilder.writeSingle(descriptorSet.get(), vertexBufferLoc, vertexBufferType, &vertexBufferDescInfo);
580 	updateBuilder.writeSingle(descriptorSet.get(), indexBufferLoc, indexBufferType, &indexBufferDescInfo);
581 	updateBuilder.update(vkd, device);
582 
583 	// Pipeline layout.
584 	const PipelineLayoutWrapper pipelineLayout (m_params.constructionType, vkd, device, setLayout.get());
585 
586 	// Shader modules.
587 	ShaderWrapper			taskModule;
588 	ShaderWrapper			fragModule;
589 	const auto&				binaries = m_context.getBinaryCollection();
590 
591 	if (binaries.contains("task"))
592 		taskModule = ShaderWrapper(vkd, device, binaries.get("task"), 0u);
593 	if (!m_params.rasterizationDisabled)
594 		fragModule = ShaderWrapper(vkd, device, binaries.get("frag"), 0u);
595 	const auto meshModule = ShaderWrapper(vkd, device, binaries.get("mesh"), 0u);
596 
597 	// Graphics pipeline.
598 	std::vector<VkViewport>	viewports		(1u, makeViewport(colorBufferExtent));
599 	std::vector<VkRect2D>	scissors		(1u, makeRect2D(colorBufferExtent));
600 	GraphicsPipelineWrapper pipelineMaker	(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.constructionType);
601 
602 	makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout, taskModule, meshModule, fragModule, renderPass.get(), viewports, scissors);
603 	const auto				pipeline		= pipelineMaker.getPipeline();
604 
605 	// Command pool and buffer.
606 	const auto cmdPool			= makeCommandPool(vkd, device, qIndex);
607 	const auto cmdBufferPtr		= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
608 	const auto cmdBuffer		= cmdBufferPtr.get();
609 
610 	// Output buffer.
611 	const auto	tcuFormat		= mapVkFormat(colorBufferFormat);
612 	const auto	outBufferSize	= static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * colorBufferExtent.width * colorBufferExtent.height);
613 	const auto	outBufferUsage	= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
614 	const auto	outBufferInfo	= makeBufferCreateInfo(outBufferSize, outBufferUsage);
615 	BufferWithMemory outBuffer (vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible);
616 	auto&		outBufferAlloc	= outBuffer.getAllocation();
617 	void*		outBufferData	= outBufferAlloc.getHostPtr();
618 
619 	// Draw triangle.
620 	beginCommandBuffer(vkd, cmdBuffer);
621 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), getClearColor());
622 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
623 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
624 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, m_params.taskCount, 1u, 1u);
625 	endRenderPass(vkd, cmdBuffer);
626 
627 	// Copy color buffer to output buffer.
628 	const tcu::IVec3 imageDim	(static_cast<int>(colorBufferExtent.width), static_cast<int>(colorBufferExtent.height), static_cast<int>(colorBufferExtent.depth));
629 	const tcu::IVec2 imageSize	(imageDim.x(), imageDim.y());
630 
631 	copyImageToBuffer(vkd, cmdBuffer, colorBuffer.get(), outBuffer.get(), imageSize);
632 	endCommandBuffer(vkd, cmdBuffer);
633 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
634 
635 	// Invalidate alloc.
636 	invalidateAlloc(vkd, device, outBufferAlloc);
637 	tcu::ConstPixelBufferAccess outPixels(tcuFormat, imageDim, outBufferData);
638 
639 	auto& log = m_context.getTestContext().getLog();
640 	const tcu::Vec4 threshold (0.0f); // The color can be represented exactly.
641 
642 	if (!tcu::floatThresholdCompare(log, "Result", "", m_params.expectedColor, outPixels, threshold, tcu::COMPARE_LOG_EVERYTHING))
643 		return tcu::TestStatus::fail("Failed; check log for details");
644 
645 	return tcu::TestStatus::pass("Pass");
646 }
647 
gradientImageExtent()648 VkExtent3D gradientImageExtent ()
649 {
650 	return makeExtent3D(256u, 256u, 1u);
651 }
652 
653 struct GradientParams
654 {
655 	tcu::Maybe<FragmentSize> fragmentSize;
656 	PipelineConstructionType constructionType;
657 
GradientParamsvkt::MeshShader::__anon4a1cb0ed0111::GradientParams658 	GradientParams (const tcu::Maybe<FragmentSize>& fragmentSize_, PipelineConstructionType constructionType_)
659 		: fragmentSize		(fragmentSize_)
660 		, constructionType	(constructionType_)
661 		{}
662 };
663 
checkMeshSupport(Context & context,GradientParams params)664 void checkMeshSupport (Context& context, GradientParams params)
665 {
666 	checkTaskMeshShaderSupportEXT(context, false, true);
667 
668 	if (static_cast<bool>(params.fragmentSize))
669 	{
670 		const auto& features = context.getMeshShaderFeaturesEXT();
671 		if (!features.primitiveFragmentShadingRateMeshShader)
672 			TCU_THROW(NotSupportedError, "Primitive fragment shading rate not supported in mesh shaders");
673 	}
674 
675 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.constructionType);
676 }
677 
initGradientPrograms(vk::SourceCollections & programCollection,GradientParams params)678 void initGradientPrograms (vk::SourceCollections& programCollection, GradientParams params)
679 {
680 	const auto buildOptions	= getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
681 	const auto extent		= gradientImageExtent();
682 
683 	std::ostringstream frag;
684 	frag
685 		<< "#version 450\n"
686 		<< "\n"
687 		<< "layout (location=0) in  vec4 inColor;\n"
688 		<< "layout (location=0) out vec4 outColor;\n"
689 		<< "\n"
690 		<< "void main ()\n"
691 		<< "{\n"
692 		<< "    outColor = inColor;\n"
693 		<< "}\n"
694 		;
695 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
696 
697 	std::string fragmentSizeStr;
698 	const auto useFragmentSize	= static_cast<bool>(params.fragmentSize);
699 
700 	if (useFragmentSize)
701 	{
702 		const auto& fragSize = params.fragmentSize.get();
703 		fragmentSizeStr	= getGLSLShadingRateMask(fragSize);
704 
705 		const auto val	= getSPVShadingRateValue(fragSize);
706 		DE_ASSERT(val != 0);
707 		DE_UNREF(val); // For release builds.
708 	}
709 
710 	std::ostringstream mesh;
711 	mesh
712 		<< "#version 450\n"
713 		<< "#extension GL_EXT_mesh_shader : enable\n"
714 		;
715 
716 	if (useFragmentSize)
717 		mesh << "#extension GL_EXT_fragment_shading_rate : enable\n";
718 
719 	mesh
720 		<< "\n"
721 		<< "layout(local_size_x=4) in;\n"
722 		<< "layout(triangles) out;\n"
723 		<< "layout(max_vertices=256, max_primitives=256) out;\n"
724 		<< "\n"
725 		<< "layout (location=0) out vec4 outColor[];\n"
726 		<< "\n"
727 		;
728 
729 	if (useFragmentSize)
730 	{
731 		mesh
732 			<< "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
733 			<< "   int gl_PrimitiveShadingRateEXT;\n"
734 			<< "} gl_MeshPrimitivesEXT[];\n"
735 			<< "\n"
736 			;
737 	}
738 
739 	mesh
740 		<< "void main ()\n"
741 		<< "{\n"
742 		<< "    SetMeshOutputsEXT(4u, 2u);\n"
743 		<< "\n"
744 		<< "    const uint vertex    = gl_LocalInvocationIndex;\n"
745 		<< "    const uint primitive = gl_LocalInvocationIndex;\n"
746 		<< "\n"
747 		<< "    const vec4 topLeft      = vec4(-1.0, -1.0, 0.0, 1.0);\n"
748 		<< "    const vec4 botLeft      = vec4(-1.0,  1.0, 0.0, 1.0);\n"
749 		<< "    const vec4 topRight     = vec4( 1.0, -1.0, 0.0, 1.0);\n"
750 		<< "    const vec4 botRight     = vec4( 1.0,  1.0, 0.0, 1.0);\n"
751 		<< "    const vec4 positions[4] = vec4[](topLeft, botLeft, topRight, botRight);\n"
752 		<< "\n"
753 		// Green changes according to the width.
754 		// Blue changes according to the height.
755 		// Value 0 at the center of the first pixel and value 1 at the center of the last pixel.
756 		<< "    const float width      = " << extent.width << ";\n"
757 		<< "    const float height     = " << extent.height << ";\n"
758 		<< "    const float halfWidth  = (1.0 / (width - 1.0)) / 2.0;\n"
759 		<< "    const float halfHeight = (1.0 / (height - 1.0)) / 2.0;\n"
760 		<< "    const float minGreen   = -halfWidth;\n"
761 		<< "    const float maxGreen   = 1.0+halfWidth;\n"
762 		<< "    const float minBlue    = -halfHeight;\n"
763 		<< "    const float maxBlue    = 1.0+halfHeight;\n"
764 		<< "    const vec4  colors[4]  = vec4[](\n"
765 		<< "        vec4(0, minGreen, minBlue, 1.0),\n"
766 		<< "        vec4(0, minGreen, maxBlue, 1.0),\n"
767 		<< "        vec4(0, maxGreen, minBlue, 1.0),\n"
768 		<< "        vec4(0, maxGreen, maxBlue, 1.0)\n"
769 		<< "    );\n"
770 		<< "\n"
771 		<< "    const uvec3 indices[2] = uvec3[](\n"
772 		<< "        uvec3(0, 1, 2),\n"
773 		<< "        uvec3(1, 3, 2)\n"
774 		<< "    );\n"
775 		<< "    if (vertex < 4u)\n"
776 		<< "    {\n"
777 		<< "        gl_MeshVerticesEXT[vertex].gl_Position = positions[vertex];\n"
778 		<< "        outColor[vertex] = colors[vertex];\n"
779 		<< "    }\n"
780 		<< "    if (primitive < 2u)\n"
781 		<< "    {\n"
782 		;
783 
784 	if (useFragmentSize)
785 	{
786 		mesh
787 			<< "        gl_MeshPrimitivesEXT[primitive].gl_PrimitiveShadingRateEXT = " << fragmentSizeStr << ";\n"
788 			;
789 	}
790 
791 	mesh
792 		<< "        gl_PrimitiveTriangleIndicesEXT[primitive] = indices[primitive];\n"
793 		<< "    }\n"
794 		<< "}\n"
795 		;
796 		;
797 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
798 }
799 
coordColorFormat(int x,int y,const tcu::Vec4 & color)800 std::string coordColorFormat (int x, int y, const tcu::Vec4& color)
801 {
802 	std::ostringstream msg;
803 	msg << "[" << x << ", " << y << "]=(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
804 	return msg.str();
805 }
806 
testFullscreenGradient(Context & context,GradientParams params)807 tcu::TestStatus testFullscreenGradient (Context& context, GradientParams params)
808 {
809 	const auto&		vki					= context.getInstanceInterface();
810 	const auto&		vkd					= context.getDeviceInterface();
811 	const auto		physicalDevice		= context.getPhysicalDevice();
812 	const auto		device				= context.getDevice();
813 	auto&			alloc				= context.getDefaultAllocator();
814 	const auto		qIndex				= context.getUniversalQueueFamilyIndex();
815 	const auto		queue				= context.getUniversalQueue();
816 	const auto		useFragmentSize		= static_cast<bool>(params.fragmentSize);
817 	const auto		defaultFragmentSize	= FragmentSize::SIZE_1X1;
818 	const auto		rateSize			= getShadingRateSize(useFragmentSize ? params.fragmentSize.get() : defaultFragmentSize);
819 
820 	// Color buffer.
821 	const auto	colorBufferFormat	= VK_FORMAT_R8G8B8A8_UNORM;
822 	const auto	colorBufferExtent	= makeExtent3D(256u, 256u, 1u); // Big enough for a detailed gradient, small enough to get unique colors.
823 	const auto	colorBufferUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
824 
825 	const VkImageCreateInfo colorBufferInfo =
826 	{
827 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
828 		nullptr,								//	const void*				pNext;
829 		0u,										//	VkImageCreateFlags		flags;
830 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
831 		colorBufferFormat,						//	VkFormat				format;
832 		colorBufferExtent,						//	VkExtent3D				extent;
833 		1u,										//	uint32_t				mipLevels;
834 		1u,										//	uint32_t				arrayLayers;
835 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
836 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
837 		colorBufferUsage,						//	VkImageUsageFlags		usage;
838 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
839 		0u,										//	uint32_t				queueFamilyIndexCount;
840 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
841 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
842 	};
843 	ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
844 
845 	const auto colorSRR			= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
846 	const auto colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorBufferFormat, colorSRR);
847 
848 	// Render pass.
849 	const auto renderPass = makeRenderPass(vkd, device, colorBufferFormat);
850 
851 	// Framebuffer.
852 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorBufferExtent.width, colorBufferExtent.height);
853 
854 	// Set layout.
855 	DescriptorSetLayoutBuilder layoutBuilder;
856 	const auto setLayout = layoutBuilder.build(vkd, device);
857 
858 	// Pipeline layout.
859 	const PipelineLayoutWrapper pipelineLayout (params.constructionType, vkd, device, setLayout.get());
860 
861 	// Shader modules.
862 	ShaderWrapper			taskModule;
863 	const auto&				binaries = context.getBinaryCollection();
864 
865 	const auto meshModule = ShaderWrapper(vkd, device, binaries.get("mesh"), 0u);
866 	const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag"), 0u);
867 
868 	using ShadingRateInfoPtr = de::MovePtr<VkPipelineFragmentShadingRateStateCreateInfoKHR>;
869 	ShadingRateInfoPtr pNext;
870 	if (useFragmentSize)
871 	{
872 		pNext = ShadingRateInfoPtr(new VkPipelineFragmentShadingRateStateCreateInfoKHR);
873 		*pNext = initVulkanStructure();
874 
875 		pNext->fragmentSize		= getShadingRateSize(FragmentSize::SIZE_1X1); // 1x1 will not be used as the primitive rate in tests with fragment size.
876 		pNext->combinerOps[0]	= VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR;
877 		pNext->combinerOps[1]	= VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR;
878 	}
879 
880 	// Graphics pipeline.
881 	std::vector<VkViewport>	viewports		(1u, makeViewport(colorBufferExtent));
882 	std::vector<VkRect2D>	scissors		(1u, makeRect2D(colorBufferExtent));
883 	GraphicsPipelineWrapper pipelineMaker	(vki, vkd, physicalDevice, device, context.getDeviceExtensions(), params.constructionType);
884 
885 	makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout,
886 							 taskModule, meshModule, fragModule,
887 							 renderPass.get(), viewports, scissors, 0u, nullptr, pNext.get());
888 	const auto pipeline = pipelineMaker.getPipeline();
889 
890 	// Command pool and buffer.
891 	const auto cmdPool			= makeCommandPool(vkd, device, qIndex);
892 	const auto cmdBufferPtr		= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
893 	const auto cmdBuffer		= cmdBufferPtr.get();
894 
895 	// Output buffer.
896 	const auto	tcuFormat		= mapVkFormat(colorBufferFormat);
897 	const auto	outBufferSize	= static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * colorBufferExtent.width * colorBufferExtent.height);
898 	const auto	outBufferUsage	= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
899 	const auto	outBufferInfo	= makeBufferCreateInfo(outBufferSize, outBufferUsage);
900 	BufferWithMemory outBuffer (vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible);
901 	auto&		outBufferAlloc	= outBuffer.getAllocation();
902 	void*		outBufferData	= outBufferAlloc.getHostPtr();
903 
904 	// Draw triangles.
905 	beginCommandBuffer(vkd, cmdBuffer);
906 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), getClearColor());
907 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
908 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
909 	endRenderPass(vkd, cmdBuffer);
910 
911 	// Copy color buffer to output buffer.
912 	const tcu::IVec3 imageDim	(static_cast<int>(colorBufferExtent.width), static_cast<int>(colorBufferExtent.height), static_cast<int>(colorBufferExtent.depth));
913 	const tcu::IVec2 imageSize	(imageDim.x(), imageDim.y());
914 
915 	copyImageToBuffer(vkd, cmdBuffer, colorBuffer.get(), outBuffer.get(), imageSize);
916 	endCommandBuffer(vkd, cmdBuffer);
917 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
918 
919 	// Invalidate alloc.
920 	invalidateAlloc(vkd, device, outBufferAlloc);
921 	tcu::ConstPixelBufferAccess outPixels(tcuFormat, imageDim, outBufferData);
922 
923 	// Create reference image.
924 	tcu::TextureLevel		refLevel	(tcuFormat, imageDim.x(), imageDim.y(), imageDim.z());
925 	tcu::PixelBufferAccess	refAccess	(refLevel);
926 	for (int y = 0; y < imageDim.y(); ++y)
927 		for (int x = 0; x < imageDim.x(); ++x)
928 		{
929 			const tcu::IVec4 color (0, x, y, 255);
930 			refAccess.setPixel(color, x, y);
931 		}
932 
933 	const tcu::TextureFormat	maskFormat	(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
934 	tcu::TextureLevel			errorMask	(maskFormat, imageDim.x(), imageDim.y(), imageDim.z());
935 	tcu::PixelBufferAccess		errorAccess	(errorMask);
936 	const tcu::Vec4				green		(0.0f, 1.0f, 0.0f, 1.0f);
937 	const tcu::Vec4				red			(1.0f, 0.0f, 0.0f, 1.0f);
938 	auto&						log			= context.getTestContext().getLog();
939 
940 	// Each block needs to have the same color and be equal to one of the pixel colors of that block in the reference image.
941 	const auto blockWidth	= static_cast<int>(rateSize.width);
942 	const auto blockHeight	= static_cast<int>(rateSize.height);
943 
944 	tcu::clear(errorAccess, green);
945 	bool globalFail = false;
946 
947 	for (int y = 0; y < imageDim.y() / blockHeight; ++y)
948 		for (int x = 0; x < imageDim.x() / blockWidth; ++x)
949 		{
950 			bool					blockFail	= false;
951 			std::vector<tcu::Vec4>	candidates;
952 
953 			candidates.reserve(rateSize.width * rateSize.height);
954 
955 			const auto cornerY		= y * blockHeight;
956 			const auto cornerX		= x * blockWidth;
957 			const auto cornerColor	= outPixels.getPixel(cornerX, cornerY);
958 
959 			for (int blockY = 0; blockY < blockHeight; ++blockY)
960 				for (int blockX = 0; blockX < blockWidth; ++blockX)
961 				{
962 					const auto absY		= cornerY + blockY;
963 					const auto absX		= cornerX + blockX;
964 					const auto resColor	= outPixels.getPixel(absX, absY);
965 
966 					candidates.push_back(refAccess.getPixel(absX, absY));
967 
968 					if (cornerColor != resColor)
969 					{
970 						std::ostringstream msg;
971 						msg << "Block not uniform: "
972 							<< coordColorFormat(cornerX, cornerY, cornerColor)
973 							<< " vs "
974 							<< coordColorFormat(absX, absY, resColor);
975 						log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
976 
977 						blockFail = true;
978 					}
979 				}
980 
981 			if (!de::contains(begin(candidates), end(candidates), cornerColor))
982 			{
983 				std::ostringstream msg;
984 				msg << "Block color does not match any reference color at [" << cornerX << ", " << cornerY << "]";
985 				log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
986 				blockFail = true;
987 			}
988 
989 			if (blockFail)
990 			{
991 				const auto blockAccess = tcu::getSubregion(errorAccess, cornerX, cornerY, blockWidth, blockHeight);
992 				tcu::clear(blockAccess, red);
993 				globalFail = true;
994 			}
995 		}
996 
997 	if (globalFail)
998 	{
999 		log << tcu::TestLog::Image("Result", "", outPixels);
1000 		log << tcu::TestLog::Image("Reference", "", refAccess);
1001 		log << tcu::TestLog::Image("ErrorMask", "", errorAccess);
1002 
1003 		TCU_FAIL("Color mismatch; check log for more details");
1004 	}
1005 
1006 	return tcu::TestStatus::pass("Pass");
1007 }
1008 
1009 // Smoke test that emits one triangle per pixel plus one more global background triangle, but doesn't use every triangle. It only
1010 // draws half the front triangles. It gets information from a mix of vertex buffers, per primitive buffers and push constants.
1011 struct PartialUsageParams
1012 {
1013 	PipelineConstructionType	constructionType;
1014 	bool						compactVertices;
1015 };
1016 
1017 class PartialUsageCase : public vkt::TestCase
1018 {
1019 public:
1020 	static constexpr uint32_t kWidth            = 16u;
1021 	static constexpr uint32_t kHeight           = 16u;
1022 	static constexpr uint32_t kLocalInvocations = 64u;
1023 	static constexpr uint32_t kMaxPrimitives    = kLocalInvocations;
1024 	static constexpr uint32_t kMaxVertices      = kMaxPrimitives * 3u;
1025 	static constexpr uint32_t kNumWorkGroups    = 2u;
1026 	static constexpr uint32_t kTotalPrimitives  = kNumWorkGroups * kMaxPrimitives;
1027 
PartialUsageCase(tcu::TestContext & testCtx,const std::string & name,const PartialUsageParams & params)1028 					PartialUsageCase	(tcu::TestContext& testCtx, const std::string& name, const PartialUsageParams& params)
1029 						: vkt::TestCase(testCtx, name)
1030 						, m_params(params)
1031 						{}
~PartialUsageCase(void)1032 	virtual			~PartialUsageCase	(void) {}
1033 
1034 	void			checkSupport		(Context& context) const override;
1035 	void			initPrograms		(vk::SourceCollections& programCollection) const override;
1036 	TestInstance*	createInstance		(Context& context) const override;
1037 
1038 	struct IndexAndColor
1039 	{
1040 		uint32_t	index;
1041 		float		color;
1042 	};
1043 
1044 	struct PushConstants
1045 	{
1046 		uint32_t	totalTriangles;
1047 		float		depth;
1048 		float		red;
1049 	};
1050 
1051 protected:
1052 	PartialUsageParams m_params;
1053 };
1054 
1055 class PartialUsageInstance : public vkt::TestInstance
1056 {
1057 public:
PartialUsageInstance(Context & context,PipelineConstructionType constructionType)1058 						PartialUsageInstance	(Context& context, PipelineConstructionType constructionType)
1059 							: vkt::TestInstance		(context)
1060 							, m_constructionType	(constructionType)
1061 							{}
~PartialUsageInstance(void)1062 	virtual				~PartialUsageInstance	(void) {}
1063 
1064 	tcu::TestStatus		iterate					(void) override;
1065 
1066 protected:
1067 	const PipelineConstructionType m_constructionType;
1068 };
1069 
checkSupport(Context & context) const1070 void PartialUsageCase::checkSupport (Context& context) const
1071 {
1072 	checkTaskMeshShaderSupportEXT(context, true, true);
1073 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.constructionType);
1074 }
1075 
createInstance(Context & context) const1076 TestInstance* PartialUsageCase::createInstance (Context &context) const
1077 {
1078 	return new PartialUsageInstance(context, m_params.constructionType);
1079 }
1080 
initPrograms(vk::SourceCollections & programCollection) const1081 void PartialUsageCase::initPrograms (vk::SourceCollections &programCollection) const
1082 {
1083 	const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1084 
1085 	// The task shader will always emit two mesh shader work groups, which may do some work.
1086 	std::ostringstream task;
1087 	task
1088 		<< "#version 450\n"
1089 		<< "#extension GL_EXT_mesh_shader : enable\n"
1090 		<< "\n"
1091 		<< "layout (local_size_x=1) in;\n"
1092 		<< "\n"
1093 		<< "void main ()\n"
1094 		<< "{\n"
1095 		<< "    EmitMeshTasksEXT(" << kNumWorkGroups << ", 1u, 1u);\n"
1096 		<< "}\n"
1097 		;
1098 	programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << buildOptions;
1099 
1100 	// The frag shader will color the output with the indicated color;
1101 	std::ostringstream frag;
1102 	frag
1103 		<< "#version 450\n"
1104 		<< "#extension GL_EXT_mesh_shader : enable\n"
1105 		<< "\n"
1106 		<< "layout (location=0) perprimitiveEXT in vec4 primitiveColor;\n"
1107 		<< "layout (location=0) out vec4 outColor;\n"
1108 		<< "\n"
1109 		<< "void main ()\n"
1110 		<< "{\n"
1111 		<< "    outColor = primitiveColor;\n"
1112 		<< "}\n"
1113 		;
1114 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str()) << buildOptions;
1115 
1116 	// The mesh shader reads primitive indices and vertices data from buffers and push constants. The primitive data block contains
1117 	// primitive indices and primitive colors that must be read by the current invocation using an index that depends on its global
1118 	// invocation index. The primitive index allows access into the triangle vertices buffer. Depending on the current work group
1119 	// index and total number of triangles (set by push constants), the current invocation may have to emit a primitive or not.
1120 	//
1121 	// In addition, the non-compacted variant emits some extra unused vertices at the start of the array.
1122 	const auto kExtraVertices		= (m_params.compactVertices ? 0u : kLocalInvocations);
1123 	const auto kLocationMaxVertices	= kMaxVertices + kExtraVertices;
1124 
1125 	if (!m_params.compactVertices)
1126 		DE_ASSERT(kLocationMaxVertices <= 256u);
1127 
1128 	std::ostringstream mesh;
1129 	mesh
1130 		<< "#version 450\n"
1131 		<< "#extension GL_EXT_mesh_shader : enable\n"
1132 		<< "\n"
1133 		<< "layout (local_size_x=" << kLocalInvocations << ", local_size_y=1, local_size_z=1) in;\n"
1134 		<< "layout (triangles) out;\n"
1135 		<< "layout (max_vertices=" << kLocationMaxVertices << ", max_primitives=" << kMaxPrimitives << ") out;\n"
1136 		<< "\n"
1137 		<< "layout (location=0) perprimitiveEXT out vec4 primitiveColor[];\n"
1138 		<< "\n"
1139 		<< "layout (set=0, binding=0, std430) readonly buffer VerticesBlock {\n"
1140 		<< "    vec2 coords[];\n" // 3 vertices per triangle.
1141 		<< "} vertex;\n"
1142 		<< "\n"
1143 		<< "struct IndexAndColor {\n"
1144 		<< "    uint  index;\n"   // Triangle index (for accessing the coordinates buffer above).
1145 		<< "    float color;\n"   // Triangle blue color component.
1146 		<< "};\n"
1147 		<< "\n"
1148 		<< "layout (set=0, binding=1, std430) readonly buffer PrimitiveDataBlock {\n"
1149 		<< "    IndexAndColor data[];\n"
1150 		<< "} primitive;\n"
1151 		<< "\n"
1152 		<< "layout (push_constant, std430) uniform PushConstantBlock {\n"
1153 		<< "    uint  totalTriangles;\n" // How many triangles in total we have to emit.
1154 		<< "    float depth;\n"          // Triangle depth (allows painting the background with a different color).
1155 		<< "    float red;\n"            // Triangle red color component.
1156 		<< "} pc;\n"
1157 		<< "\n"
1158 		<< "void main ()\n"
1159 		<< "{\n"
1160 		// First primitive for this work group, plus the work group primitive and vertex count.
1161 		<< "    const uint firstPrimitive   = gl_WorkGroupID.x * gl_WorkGroupSize.x;\n"
1162 		<< "    const uint wgTriangleCount  = ((pc.totalTriangles >= firstPrimitive) ? min(pc.totalTriangles - firstPrimitive, " << kLocalInvocations << ") : 0u);\n"
1163 		<< "    const uint wgVertexCount    = wgTriangleCount * 3u + " << kExtraVertices << "u;\n"
1164 		<< "\n"
1165 		;
1166 
1167 	if (!m_params.compactVertices)
1168 	{
1169 		// Produce extra unused vertices.
1170 		mesh
1171 			<< "    {\n"
1172 			<< "        const float proportion = float(gl_LocalInvocationIndex) / float(gl_WorkGroupSize.x);\n"
1173 			<< "        gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(proportion, 1.0 - proportion, pc.depth, 1.0);\n"
1174 			<< "    }\n"
1175 			<< "\n"
1176 			;
1177 	}
1178 
1179 	mesh
1180 		<< "    SetMeshOutputsEXT(wgVertexCount, wgTriangleCount);\n"
1181 		<< "\n"
1182 		// Calculate global invocation primitive id, and use it to access the per-primitive buffer. From there, get the primitive index in the
1183 		// vertex buffer and the blue color component.
1184 		<< "    if (gl_LocalInvocationIndex < wgTriangleCount) {\n"
1185 		<< "        const uint  primitiveID         = firstPrimitive + gl_LocalInvocationIndex;\n"
1186 		<< "        const uint  primitiveIndex      = primitive.data[primitiveID].index;\n"
1187 		<< "        const float blue                = primitive.data[primitiveID].color;\n"
1188 		<< "        const uint  firstVertexIndex    = primitiveIndex * 3u;\n"
1189 		<< "        const uvec3 globalVertexIndices = uvec3(firstVertexIndex, firstVertexIndex+1u, firstVertexIndex+2u);\n"
1190 		<< "        const uint  localPrimitiveID    = gl_LocalInvocationIndex;\n"
1191 		<< "        const uint  firstLocalVertex    = localPrimitiveID * 3u + " << kExtraVertices << "u;\n"
1192 		<< "        const uvec3 localVertexIndices  = uvec3(firstLocalVertex, firstLocalVertex+1u, firstLocalVertex+2u);\n"
1193 		<< "\n"
1194 		<< "        gl_MeshVerticesEXT[localVertexIndices.x].gl_Position = vec4(vertex.coords[globalVertexIndices.x], pc.depth, 1.0);\n"
1195 		<< "        gl_MeshVerticesEXT[localVertexIndices.y].gl_Position = vec4(vertex.coords[globalVertexIndices.y], pc.depth, 1.0);\n"
1196 		<< "        gl_MeshVerticesEXT[localVertexIndices.z].gl_Position = vec4(vertex.coords[globalVertexIndices.z], pc.depth, 1.0);\n"
1197 		<< "\n"
1198 		<< "        gl_PrimitiveTriangleIndicesEXT[localPrimitiveID] = localVertexIndices;\n"
1199 		<< "        primitiveColor[localPrimitiveID]                 = vec4(pc.red, 0.0, blue, 1.0f);\n"
1200 		<< "    }\n"
1201 		<< "}\n"
1202 		;
1203 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
1204 }
1205 
pixelToFBCoords(uint32_t pixelId,uint32_t totalPixels)1206 inline float pixelToFBCoords (uint32_t pixelId, uint32_t totalPixels)
1207 {
1208 	return (static_cast<float>(pixelId) + 0.5f) / static_cast<float>(totalPixels) * 2.0f - 1.0f;
1209 }
1210 
iterate()1211 tcu::TestStatus PartialUsageInstance::iterate ()
1212 {
1213 	const auto&			vki					= m_context.getInstanceInterface();
1214 	const auto&			vkd					= m_context.getDeviceInterface();
1215 	const auto			physicalDevice		= m_context.getPhysicalDevice();
1216 	const auto			device				= m_context.getDevice();
1217 	const auto			queueIndex			= m_context.getUniversalQueueFamilyIndex();
1218 	const auto			queue				= m_context.getUniversalQueue();
1219 	auto&				alloc				= m_context.getDefaultAllocator();
1220 	const auto			bufferUsage			= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1221 	const auto			bufferDescType		= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1222 	const auto			bufferDescStages	= VK_SHADER_STAGE_MESH_BIT_EXT;
1223 	const auto			pcSize				= static_cast<VkDeviceSize>(sizeof(PartialUsageCase::PushConstants));
1224 	const auto			pcStages			= bufferDescStages;
1225 	const auto			pcRange				= makePushConstantRange(pcStages, 0u, static_cast<uint32_t>(pcSize));
1226 	const auto			fbExtent			= makeExtent3D(PartialUsageCase::kWidth, PartialUsageCase::kHeight, 1u);
1227 	const tcu::IVec3	iExtent				(static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(fbExtent.depth));
1228 	const auto			colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1229 	const auto			colorTcuFormat		= mapVkFormat(colorFormat);
1230 	const auto			dsFormat			= VK_FORMAT_D16_UNORM;
1231 	const auto			vertexSize			= sizeof(tcu::Vec2);
1232 	const auto			verticesPerTriangle	= 3u;
1233 	const auto			pixelCount			= fbExtent.width * fbExtent.height * fbExtent.depth;
1234 	const auto			vertexCount			= pixelCount * verticesPerTriangle;
1235 	const auto			triangleSize		= vertexSize * verticesPerTriangle;
1236 	const auto			colorThreshold		= 0.005f; // 1/255 < 0.005 < 2/255
1237 	const float			fgRed				= 0.0f;
1238 	const float			bgRed				= 1.0f;
1239 	const float			bgBlue				= 1.0f;
1240 
1241 	// Quarter of the pixel width and height in framebuffer coordinates.
1242 	const float			pixelWidth4			= 2.0f / (static_cast<float>(fbExtent.width) * 4.0f);
1243 	const float			pixelHeight4		= 2.0f / (static_cast<float>(fbExtent.height) * 4.0f);
1244 
1245 	// Offsets for each triangle vertex from the pixel center.
1246 	//	+-------------------+
1247 	//	|         2         |
1248 	//	|         x         |
1249 	//	|        x x        |
1250 	//	|       x   x       |
1251 	//	|      x  x  x      |
1252 	//	|     x       x     |
1253 	//	|    xxxxxxxxxxx    |
1254 	//	|   0           1   |
1255 	//	+-------------------+
1256 	const std::vector<tcu::Vec2> offsets
1257 	{
1258 		tcu::Vec2(-pixelWidth4, +pixelHeight4),
1259 		tcu::Vec2(+pixelWidth4, +pixelHeight4),
1260 		tcu::Vec2(        0.0f, -pixelHeight4),
1261 	};
1262 
1263 	// We'll use two draw calls: triangles on the front and triangle that sets the background color, so we need two vertex buffers
1264 	// and two primitive data buffers.
1265 	const auto			vertexBufferFrontSize	= static_cast<VkDeviceSize>(triangleSize * pixelCount);
1266 	const auto			vertexBufferFrontInfo	= makeBufferCreateInfo(vertexBufferFrontSize, bufferUsage);
1267 	BufferWithMemory	vertexBufferFront		(vkd, device, alloc, vertexBufferFrontInfo, MemoryRequirement::HostVisible);
1268 	auto&				vertexBufferFrontAlloc	= vertexBufferFront.getAllocation();
1269 	void*				vertexBufferFrontData	= vertexBufferFrontAlloc.getHostPtr();
1270 
1271 	std::vector<tcu::Vec2> trianglePerPixel;
1272 	trianglePerPixel.reserve(vertexCount);
1273 
1274 	// Fill front vertex buffer.
1275 	for (uint32_t y = 0u; y < PartialUsageCase::kHeight; ++y)
1276 		for (uint32_t x = 0u; x < PartialUsageCase::kWidth; ++x)
1277 			for (uint32_t v = 0u; v < verticesPerTriangle; ++v)
1278 			{
1279 				const auto&	offset = offsets.at(v);
1280 				const auto	xCoord = pixelToFBCoords(x, PartialUsageCase::kWidth) + offset.x();
1281 				const auto	yCoord = pixelToFBCoords(y, PartialUsageCase::kHeight) + offset.y();
1282 				trianglePerPixel.emplace_back(xCoord, yCoord);
1283 			}
1284 	deMemcpy(vertexBufferFrontData, trianglePerPixel.data(), de::dataSize(trianglePerPixel));
1285 
1286 	// For the front triangles we will select some pixels randomly.
1287 	using IndexAndColor = PartialUsageCase::IndexAndColor;
1288 
1289 	std::set<uint32_t>			selectedPixels;
1290 	std::vector<IndexAndColor>	indicesAndColors;
1291 	de::Random					rnd					(1646058327u);
1292 	const auto					maxId				= static_cast<int>(pixelCount) - 1;
1293 	const auto					fTotalTriangles		= static_cast<float>(PartialUsageCase::kTotalPrimitives);
1294 
1295 	while (selectedPixels.size() < PartialUsageCase::kTotalPrimitives)
1296 	{
1297 		const auto pixelId = static_cast<uint32_t>(rnd.getInt(0, maxId));
1298 		if (!selectedPixels.count(pixelId))
1299 		{
1300 			selectedPixels.insert(pixelId);
1301 
1302 			const float			colorVal		= static_cast<float>(selectedPixels.size()) / fTotalTriangles;
1303 			const IndexAndColor	indexAndColor	{ pixelId, colorVal };
1304 
1305 			indicesAndColors.push_back(indexAndColor);
1306 		}
1307 	}
1308 
1309 	const auto			primDataBufferFrontSize		= static_cast<VkDeviceSize>(de::dataSize(indicesAndColors));
1310 	const auto			primDataBufferFrontInfo		= makeBufferCreateInfo(primDataBufferFrontSize, bufferUsage);
1311 	BufferWithMemory	primDataBufferFront			(vkd, device, alloc, primDataBufferFrontInfo, MemoryRequirement::HostVisible);
1312 	auto&				primDataBufferFrontAlloc	= primDataBufferFront.getAllocation();
1313 	void*				primDataBufferFrontData		= primDataBufferFrontAlloc.getHostPtr();
1314 	deMemcpy(primDataBufferFrontData, indicesAndColors.data(), de::dataSize(indicesAndColors));
1315 
1316 	// Generate reference image based on the previous data.
1317 	tcu::TextureLevel		referenceLevel	(colorTcuFormat, iExtent.x(), iExtent.y(), iExtent.z());
1318 	tcu::PixelBufferAccess	referenceAccess	= referenceLevel.getAccess();
1319 	const tcu::Vec4			bgColor			(bgRed, 0.0f, bgBlue, 1.0f);
1320 
1321 	tcu::clear(referenceAccess, bgColor);
1322 	for (const auto& indexAndColor : indicesAndColors)
1323 	{
1324 		const int		xCoord	= static_cast<int>(indexAndColor.index % fbExtent.width);
1325 		const int		yCoord	= static_cast<int>(indexAndColor.index / fbExtent.width);
1326 		const tcu::Vec4	color	(fgRed, 0.0f, indexAndColor.color, 1.0f);
1327 
1328 		referenceAccess.setPixel(color, xCoord, yCoord);
1329 	}
1330 
1331 	// Background buffers. These will only contain one triangle.
1332 	const std::vector<tcu::Vec2> backgroundTriangle
1333 	{
1334 		tcu::Vec2(-1.0f, -1.0f),
1335 		tcu::Vec2(-1.0f,  3.0f),
1336 		tcu::Vec2( 3.0f, -1.0f),
1337 	};
1338 
1339 	const PartialUsageCase::IndexAndColor backgroundTriangleData { 0u, bgBlue };
1340 
1341 	const auto			vertexBufferBackSize	= static_cast<VkDeviceSize>(de::dataSize(backgroundTriangle));
1342 	const auto			vertexBufferBackInfo	= makeBufferCreateInfo(vertexBufferBackSize, bufferUsage);
1343 	BufferWithMemory	vertexBufferBack		(vkd, device, alloc, vertexBufferBackInfo, MemoryRequirement::HostVisible);
1344 	auto&				vertexBufferBackAlloc	= vertexBufferBack.getAllocation();
1345 	void*				vertexBufferBackData	= vertexBufferBackAlloc.getHostPtr();
1346 	deMemcpy(vertexBufferBackData, backgroundTriangle.data(), de::dataSize(backgroundTriangle));
1347 
1348 	const auto			primDataBufferBackSize	= static_cast<VkDeviceSize>(sizeof(backgroundTriangleData));
1349 	const auto			primDataBufferBackInfo	= makeBufferCreateInfo(primDataBufferBackSize, bufferUsage);
1350 	BufferWithMemory	primDataBufferBack		(vkd, device, alloc, primDataBufferBackInfo, MemoryRequirement::HostVisible);
1351 	auto&				primDataBufferBackAlloc	= primDataBufferBack.getAllocation();
1352 	void*				primDataBufferBackData	= primDataBufferBackAlloc.getHostPtr();
1353 	deMemcpy(primDataBufferBackData, &backgroundTriangleData, sizeof(backgroundTriangleData));
1354 
1355 	// Descriptor pool and descriptor sets.
1356 	DescriptorPoolBuilder poolBuilder;
1357 	poolBuilder.addType(bufferDescType, 4u);
1358 	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
1359 
1360 	DescriptorSetLayoutBuilder setLayoutBuilder;
1361 	setLayoutBuilder.addSingleBinding(bufferDescType, bufferDescStages);
1362 	setLayoutBuilder.addSingleBinding(bufferDescType, bufferDescStages);
1363 	const auto setLayout = setLayoutBuilder.build(vkd, device);
1364 
1365 	const auto setFront	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1366 	const auto setBack	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1367 
1368 	// Update descriptor sets.
1369 	DescriptorSetUpdateBuilder updateBuilder;
1370 	{
1371 		const auto bufferInfo = makeDescriptorBufferInfo(vertexBufferFront.get(), 0ull, vertexBufferFrontSize);
1372 		updateBuilder.writeSingle(setFront.get(), DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescType, &bufferInfo);
1373 	}
1374 	{
1375 		const auto bufferInfo = makeDescriptorBufferInfo(primDataBufferFront.get(), 0ull, primDataBufferFrontSize);
1376 		updateBuilder.writeSingle(setFront.get(), DescriptorSetUpdateBuilder::Location::binding(1u), bufferDescType, &bufferInfo);
1377 	}
1378 	{
1379 		const auto bufferInfo = makeDescriptorBufferInfo(vertexBufferBack.get(), 0ull, vertexBufferBackSize);
1380 		updateBuilder.writeSingle(setBack.get(), DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescType, &bufferInfo);
1381 	}
1382 	{
1383 		const auto bufferInfo = makeDescriptorBufferInfo(primDataBufferBack.get(), 0ull, primDataBufferBackSize);
1384 		updateBuilder.writeSingle(setBack.get(), DescriptorSetUpdateBuilder::Location::binding(1u), bufferDescType, &bufferInfo);
1385 	}
1386 	updateBuilder.update(vkd, device);
1387 
1388 	// Pipeline layout.
1389 	const PipelineLayoutWrapper pipelineLayout (m_constructionType, vkd, device, setLayout.get(), &pcRange);
1390 
1391 	// Shader modules.
1392 	const auto&	binaries	= m_context.getBinaryCollection();
1393 	const auto	taskShader	= ShaderWrapper(vkd, device, binaries.get("task"));
1394 	const auto	meshShader	= ShaderWrapper(vkd, device, binaries.get("mesh"));
1395 	const auto	fragShader	= ShaderWrapper(vkd, device, binaries.get("frag"));
1396 
1397 	// Render pass.
1398 	const auto renderPass = makeRenderPass(vkd, device, colorFormat, dsFormat);
1399 
1400 	// Color and depth/stencil buffers.
1401 	const VkImageCreateInfo imageCreateInfo =
1402 	{
1403 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1404 		nullptr,								//	const void*				pNext;
1405 		0u,										//	VkImageCreateFlags		flags;
1406 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1407 		VK_FORMAT_UNDEFINED,					//	VkFormat				format;
1408 		fbExtent,								//	VkExtent3D				extent;
1409 		1u,										//	uint32_t				mipLevels;
1410 		1u,										//	uint32_t				arrayLayers;
1411 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
1412 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1413 		0u,										//	VkImageUsageFlags		usage;
1414 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1415 		0u,										//	uint32_t				queueFamilyIndexCount;
1416 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
1417 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1418 	};
1419 
1420 	std::unique_ptr<ImageWithMemory> colorAttachment;
1421 	{
1422 		auto colorAttCreateInfo		= imageCreateInfo;
1423 		colorAttCreateInfo.format	= colorFormat;
1424 		colorAttCreateInfo.usage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1425 
1426 		colorAttachment.reset(new ImageWithMemory(vkd, device, alloc, colorAttCreateInfo, MemoryRequirement::Any));
1427 	}
1428 
1429 	std::unique_ptr<ImageWithMemory> dsAttachment;
1430 	{
1431 		auto dsAttCreateInfo	= imageCreateInfo;
1432 		dsAttCreateInfo.format	= dsFormat;
1433 		dsAttCreateInfo.usage	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1434 
1435 		dsAttachment.reset(new ImageWithMemory(vkd, device, alloc, dsAttCreateInfo, MemoryRequirement::Any));
1436 	}
1437 
1438 	const auto colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1439 	const auto colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1440 	const auto dsSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
1441 
1442 	const auto colorView	= makeImageView(vkd, device, colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
1443 	const auto dsView		= makeImageView(vkd, device, dsAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSRR);
1444 
1445 	// Create verification buffer.
1446 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(tcu::getPixelSize(colorTcuFormat) * iExtent.x() * iExtent.y() * iExtent.z());
1447 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1448 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
1449 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
1450 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
1451 
1452 	// Framebuffer.
1453 	const std::vector<VkImageView>	fbViews		{ colorView.get(), dsView.get() };
1454 	const auto						framebuffer	= makeFramebuffer(
1455 		vkd, device, renderPass.get(),
1456 		static_cast<uint32_t>(fbViews.size()), de::dataOrNull(fbViews),
1457 		fbExtent.width, fbExtent.height);
1458 
1459 	// Viewports and scissors.
1460 	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
1461 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
1462 
1463 	// Pipeline.
1464 	const VkStencilOpState						stencilOpState	= {};
1465 	const VkPipelineDepthStencilStateCreateInfo	dsInfo			=
1466 	{
1467 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		//	VkStructureType							sType;
1468 		nullptr,														//	const void*								pNext;
1469 		0u,																//	VkPipelineDepthStencilStateCreateFlags	flags;
1470 		VK_TRUE,														//	VkBool32								depthTestEnable;
1471 		VK_TRUE,														//	VkBool32								depthWriteEnable;
1472 		VK_COMPARE_OP_LESS,												//	VkCompareOp								depthCompareOp;
1473 		VK_FALSE,														//	VkBool32								depthBoundsTestEnable;
1474 		VK_FALSE,														//	VkBool32								stencilTestEnable;
1475 		stencilOpState,													//	VkStencilOpState						front;
1476 		stencilOpState,													//	VkStencilOpState						back;
1477 		0.0f,															//	float									minDepthBounds;
1478 		1.0f,															//	float									maxDepthBounds;
1479 	};
1480 
1481 	GraphicsPipelineWrapper pipelineMaker(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_constructionType);
1482 	makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout,
1483 							 taskShader, meshShader, fragShader,
1484 							 renderPass.get(), viewports, scissors, 0u, &dsInfo);
1485 	const auto pipeline = pipelineMaker.getPipeline();
1486 
1487 	// Command pool and buffer.
1488 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
1489 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1490 	const auto cmdBuffer	= cmdBufferPtr.get();
1491 
1492 	// Draw the triangles in the front, then the triangle in the back.
1493 	const tcu::Vec4	clearColor		(0.0f, 0.0f, 0.0f, 1.0f);
1494 	const float		clearDepth		= 1.0f;
1495 	const uint32_t	clearStencil	= 0u;
1496 
1497 	const PartialUsageCase::PushConstants pcFront	= { PartialUsageCase::kTotalPrimitives, 0.0f, fgRed };
1498 	const PartialUsageCase::PushConstants pcBack	= { 1u, 0.5f, bgRed };
1499 
1500 	beginCommandBuffer(vkd, cmdBuffer);
1501 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor, clearDepth, clearStencil);
1502 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1503 
1504 	// Front triangles.
1505 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &setFront.get(), 0u, nullptr);
1506 	vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, static_cast<uint32_t>(pcSize), &pcFront);
1507 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
1508 
1509 	// Back triangles.
1510 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &setBack.get(), 0u, nullptr);
1511 	vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, static_cast<uint32_t>(pcSize), &pcBack);
1512 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
1513 
1514 	endRenderPass(vkd, cmdBuffer);
1515 
1516 	// Copy color attachment to verification buffer.
1517 	const auto colorToTransferBarrier	= makeImageMemoryBarrier(
1518 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1519 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1520 		colorAttachment->get(), colorSRR);
1521 	const auto transferToHostBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1522 	const auto copyRegion				= makeBufferImageCopy(fbExtent, colorSRL);
1523 
1524 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &colorToTransferBarrier);
1525 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
1526 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transferToHostBarrier);
1527 
1528 	endCommandBuffer(vkd, cmdBuffer);
1529 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1530 
1531 	// Verify color attachment.
1532 	invalidateAlloc(vkd, device, verificationBufferAlloc);
1533 
1534 	tcu::ConstPixelBufferAccess	resultAccess	(colorTcuFormat, iExtent, verificationBufferData);
1535 	auto&						log				= m_context.getTestContext().getLog();
1536 	const tcu::Vec4				errorThreshold	(colorThreshold, 0.0f, colorThreshold, 0.0f);
1537 
1538 	if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, errorThreshold, tcu::COMPARE_LOG_ON_ERROR))
1539 		TCU_FAIL("Result does not match reference -- check log for details");
1540 
1541 	return tcu::TestStatus::pass("Pass");
1542 }
1543 
1544 // Create a classic and a mesh shading pipeline using graphics pipeline libraries. Both pipelines will use the same fragment shader
1545 // pipeline library, and the fragment shader will use the gl_Layer built-in, which is per-primitive in mesh shaders and per-vertex
1546 // in vertex shaders.
1547 class SharedFragLibraryCase : public vkt::TestCase
1548 {
1549 public:
SharedFragLibraryCase(tcu::TestContext & testCtx,const std::string & name,PipelineConstructionType constructionType)1550 					SharedFragLibraryCase	(tcu::TestContext& testCtx, const std::string& name, PipelineConstructionType constructionType)
1551 						: vkt::TestCase			(testCtx, name)
1552 						, m_constructionType	(constructionType)
1553 						{}
~SharedFragLibraryCase(void)1554 	virtual			~SharedFragLibraryCase	(void) {}
1555 
1556 	void			checkSupport			(Context& context) const override;
1557 	void			initPrograms			(vk::SourceCollections& programCollection) const override;
1558 	TestInstance*	createInstance			(Context& context) const override;
1559 
1560 	static std::vector<tcu::Vec4> getLayerColors (void);
1561 
1562 protected:
1563 	PipelineConstructionType m_constructionType;
1564 };
1565 
1566 class SharedFragLibraryInstance : public vkt::TestInstance
1567 {
1568 public:
SharedFragLibraryInstance(Context & context,PipelineConstructionType constructionType)1569 						SharedFragLibraryInstance	(Context& context, PipelineConstructionType constructionType)
1570 							: vkt::TestInstance		(context)
1571 							, m_constructionType	(constructionType)
1572 							{}
~SharedFragLibraryInstance(void)1573 	virtual				~SharedFragLibraryInstance	(void) {}
1574 
1575 	tcu::TestStatus		iterate						(void) override;
1576 
1577 protected:
1578 	PipelineConstructionType m_constructionType;
1579 };
1580 
getLayerColors(void)1581 std::vector<tcu::Vec4> SharedFragLibraryCase::getLayerColors (void)
1582 {
1583 	std::vector<tcu::Vec4> layerColors
1584 	{
1585 		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
1586 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1587 		tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1588 	};
1589 
1590 	return layerColors;
1591 }
1592 
checkSupport(Context & context) const1593 void SharedFragLibraryCase::checkSupport (Context& context) const
1594 {
1595 	checkTaskMeshShaderSupportEXT(context, false/*requireTask*/, true/*requireMesh*/);
1596 
1597 	if (context.getUsedApiVersion() < VK_API_VERSION_1_2)
1598 		context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
1599 	else
1600 	{
1601 		// More fine-grained: we do not need shaderViewportIndex.
1602 		const auto& vk12Features = context.getDeviceVulkan12Features();
1603 		if (!vk12Features.shaderOutputLayer)
1604 			TCU_THROW(NotSupportedError, "shaderOutputLayer not supported");
1605 	}
1606 
1607 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
1608 }
1609 
initPrograms(vk::SourceCollections & programCollection) const1610 void SharedFragLibraryCase::initPrograms (vk::SourceCollections &programCollection) const
1611 {
1612 	const auto meshBuildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
1613 
1614 	const std::string vtxPositions =
1615 		"vec2 positions[3] = vec2[](\n"
1616 		"    vec2(-1.0, -1.0),\n"
1617 		"    vec2(-1.0, 3.0),\n"
1618 		"    vec2(3.0, -1.0)\n"
1619 		");\n"
1620 		;
1621 
1622 	// The vertex shader emits geometry to layer 1.
1623 	std::ostringstream vert;
1624 	vert
1625 		<< "#version 450\n"
1626 		<< "#extension GL_ARB_shader_viewport_layer_array : enable\n"
1627 		<< "\n"
1628 		<< vtxPositions
1629 		<< "void main ()\n"
1630 		<< "{\n"
1631 		<< "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
1632 		<< "    gl_Layer = 1;\n"
1633 		<< "}\n"
1634 		;
1635 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1636 	programCollection.glslSources.add("vert_1_2") << glu::VertexSource(vert.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
1637 
1638 	// The mesh shader emits geometry to layer 2.
1639 	std::ostringstream mesh;
1640 	mesh
1641 		<< "#version 450\n"
1642 		<< "#extension GL_EXT_mesh_shader : enable\n"
1643 		<< "\n"
1644 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1645 		<< "layout (triangles) out;\n"
1646 		<< "layout (max_vertices=3, max_primitives=1) out;\n"
1647 		<< "\n"
1648 		<< "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
1649 		<< "   int gl_Layer;\n"
1650 		<< "} gl_MeshPrimitivesEXT[];\n"
1651 		<< "\n"
1652 		<< vtxPositions
1653 		<< "void main ()\n"
1654 		<< "{\n"
1655 		<< "    SetMeshOutputsEXT(3u, 1u);\n"
1656 		<< "    for (uint i = 0; i < 3; ++i)\n"
1657 		<< "        gl_MeshVerticesEXT[i].gl_Position = vec4(positions[i], 0.0, 1.0);\n"
1658 		<< "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1659 		<< "    gl_MeshPrimitivesEXT[0].gl_Layer = 2;\n"
1660 		<< "}\n"
1661 		;
1662 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << meshBuildOptions;
1663 
1664 	// The frag shader uses the gl_Layer built-in to choose an output color.
1665 	const auto outColors = getLayerColors();
1666 	DE_ASSERT(outColors.size() == 3);
1667 
1668 	std::ostringstream frag;
1669 	frag
1670 		<< "#version 450\n"
1671 		<< "\n"
1672 		<< "layout (location=0) out vec4 outColor;\n"
1673 		<< "\n"
1674 		<< "vec4 outColors[3] = vec4[](\n"
1675 		<< "	vec4" << outColors.at(0) << ",\n"
1676 		<< "	vec4" << outColors.at(1) << ",\n"
1677 		<< "	vec4" << outColors.at(2) << "\n"
1678 		<< ");\n"
1679 		<< "\n"
1680 		<< "void main ()\n"
1681 		<< "{\n"
1682 		<< "	outColor = outColors[gl_Layer];\n"
1683 		<< "}\n"
1684 		;
1685 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1686 }
1687 
createInstance(Context & context) const1688 TestInstance* SharedFragLibraryCase::createInstance (Context& context) const
1689 {
1690 	return new SharedFragLibraryInstance(context, m_constructionType);
1691 }
1692 
makeLibCreateInfo(VkGraphicsPipelineLibraryFlagsEXT flags,void * pNext=nullptr)1693 VkGraphicsPipelineLibraryCreateInfoEXT makeLibCreateInfo (VkGraphicsPipelineLibraryFlagsEXT flags, void* pNext = nullptr)
1694 {
1695 	const VkGraphicsPipelineLibraryCreateInfoEXT createInfo =
1696 	{
1697 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,	//	VkStructureType						sType;
1698 		pNext,															//	void*								pNext;
1699 		flags,															//	VkGraphicsPipelineLibraryFlagsEXT	flags;
1700 	};
1701 
1702 	return createInfo;
1703 }
1704 
iterate(void)1705 tcu::TestStatus SharedFragLibraryInstance::iterate (void)
1706 {
1707 	const auto&			vkd					= m_context.getDeviceInterface();
1708 	const auto&			device				= m_context.getDevice();
1709 	const auto			queueIndex			= m_context.getUniversalQueueFamilyIndex();
1710 	const auto			queue				= m_context.getUniversalQueue();
1711 	auto&				alloc				= m_context.getDefaultAllocator();
1712 	const auto			layerColors			= SharedFragLibraryCase::getLayerColors();
1713 	const auto&			clearColor			= layerColors.front();
1714 	const auto			layerCount			= static_cast<uint32_t>(layerColors.size());
1715 	const auto			fbExtent			= makeExtent3D(1u, 1u, 1u);
1716 	const tcu::IVec3	iExtent				(static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(layerCount));
1717 	const auto			fbFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1718 	const auto			tcuFormat			= mapVkFormat(fbFormat);
1719 	const auto			pixelSize			= tcu::getPixelSize(tcuFormat);
1720 	const auto			pixelCount			= fbExtent.width * fbExtent.height * layerCount;
1721 	const auto			fbUsage				= (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1722 	const bool			optimized			= (m_constructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
1723 	const auto			libExtraFlags		= (optimized ? VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT : 0);
1724 	const auto			libCompileFlags		= (VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | libExtraFlags);
1725 	const auto			pipelineLinkFlags	= (optimized ? VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT : 0);
1726 
1727 	// Color buffer.
1728 	const VkImageCreateInfo colorBufferCreateInfo =
1729 	{
1730 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1731 		nullptr,								//	const void*				pNext;
1732 		0u,										//	VkImageCreateFlags		flags;
1733 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1734 		fbFormat,								//	VkFormat				format;
1735 		fbExtent,								//	VkExtent3D				extent;
1736 		1u,										//	uint32_t				mipLevels;
1737 		layerCount,								//	uint32_t				arrayLayers;
1738 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
1739 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1740 		fbUsage,								//	VkImageUsageFlags		usage;
1741 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1742 		0u,										//	uint32_t				queueFamilyIndexCount;
1743 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
1744 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1745 	};
1746 
1747 	ImageWithMemory	colorBuffer		(vkd, device, alloc, colorBufferCreateInfo, MemoryRequirement::Any);
1748 	const auto		colorBufferSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, layerCount);
1749 	const auto		colorBufferSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, layerCount);
1750 	const auto		colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D_ARRAY, fbFormat, colorBufferSRR);
1751 
1752 	// Render pass.
1753 	const auto renderPass = makeRenderPass(vkd, device, fbFormat);
1754 
1755 	// Framebuffer.
1756 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), fbExtent.width, fbExtent.height, layerCount);
1757 
1758 	// Verification buffer.
1759 	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(static_cast<int>(pixelCount) * pixelSize);
1760 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1761 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
1762 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
1763 	void*				verificationBufferData	= verificationBufferAlloc.getHostPtr();
1764 
1765 	// Pipeline layout (common).
1766 	const auto pipelineLayout = makePipelineLayout(vkd, device);
1767 
1768 	// Shader modules.
1769 	const auto&	binaries	= m_context.getBinaryCollection();
1770 	const auto	vertModule	= createShaderModule(vkd, device, (m_context.contextSupports(VK_API_VERSION_1_2)) ? binaries.get("vert_1_2") : binaries.get("vert"));
1771 	const auto	meshModule	= createShaderModule(vkd, device, binaries.get("mesh"));
1772 	const auto	fragModule	= createShaderModule(vkd, device, binaries.get("frag"));
1773 
1774 	// Fragment output state library (common).
1775 	const VkColorComponentFlags					colorComponentFlags			= (	VK_COLOR_COMPONENT_R_BIT
1776 																			|	VK_COLOR_COMPONENT_G_BIT
1777 																			|	VK_COLOR_COMPONENT_B_BIT
1778 																			|	VK_COLOR_COMPONENT_A_BIT);
1779 	const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
1780 	{
1781 		VK_FALSE,				// VkBool32					blendEnable
1782 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcColorBlendFactor
1783 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor
1784 		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp
1785 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcAlphaBlendFactor
1786 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor
1787 		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp
1788 		colorComponentFlags,	// VkColorComponentFlags	colorWriteMask
1789 	};
1790 
1791 	const VkPipelineColorBlendStateCreateInfo colorBlendState =
1792 	{
1793 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
1794 		nullptr,													//	const void*									pNext;
1795 		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
1796 		VK_FALSE,													//	VkBool32									logicOpEnable;
1797 		VK_LOGIC_OP_CLEAR,											//	VkLogicOp									logicOp;
1798 		1u,															//	uint32_t									attachmentCount;
1799 		&colorBlendAttachmentState,									//	const VkPipelineColorBlendAttachmentState*	pAttachments;
1800 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
1801 	};
1802 
1803 	const VkPipelineMultisampleStateCreateInfo multisampleState =
1804 	{
1805 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType								sType
1806 		nullptr,													// const void*									pNext
1807 		0u,															// VkPipelineMultisampleStateCreateFlags		flags
1808 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits						rasterizationSamples
1809 		VK_FALSE,													// VkBool32										sampleShadingEnable
1810 		1.0f,														// float										minSampleShading
1811 		nullptr,													// const VkSampleMask*							pSampleMask
1812 		VK_FALSE,													// VkBool32										alphaToCoverageEnable
1813 		VK_FALSE													// VkBool32										alphaToOneEnable
1814 	};
1815 
1816 	const auto fragOutputLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
1817 
1818 	VkGraphicsPipelineCreateInfo fragOutputInfo	= initVulkanStructure();
1819 	fragOutputInfo.layout						= pipelineLayout.get();
1820 	fragOutputInfo.renderPass					= renderPass.get();
1821 	fragOutputInfo.pColorBlendState				= &colorBlendState;
1822 	fragOutputInfo.pMultisampleState			= &multisampleState;
1823 	fragOutputInfo.flags						= libCompileFlags;
1824 	fragOutputInfo.pNext						= &fragOutputLibInfo;
1825 
1826 	const auto fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputInfo);
1827 
1828 	// Fragment shader lib (shared among the classic and mesh pipelines).
1829 	const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = initVulkanStructure();
1830 
1831 	const VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo =
1832 	{
1833 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
1834 		nullptr,												//	const void*							pNext;
1835 		0u,														//	VkPipelineShaderStageCreateFlags	flags;
1836 		VK_SHADER_STAGE_FRAGMENT_BIT,							//	VkShaderStageFlagBits				stage;
1837 		fragModule.get(),										//	VkShaderModule						module;
1838 		"main",													//	const char*							pName;
1839 		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
1840 	};
1841 
1842 	const auto fragShaderLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
1843 
1844 	VkGraphicsPipelineCreateInfo fragShaderInfo	= initVulkanStructure();
1845 	fragShaderInfo.layout						= pipelineLayout.get();
1846 	fragShaderInfo.renderPass					= renderPass.get();
1847 	fragShaderInfo.pMultisampleState			= &multisampleState;
1848 	fragShaderInfo.pDepthStencilState			= &depthStencilStateCreateInfo;
1849 	fragShaderInfo.stageCount					= 1u;
1850 	fragShaderInfo.pStages						= &fragShaderStageCreateInfo;
1851 	fragShaderInfo.flags						= libCompileFlags;
1852 	fragShaderInfo.pNext						= &fragShaderLibInfo;
1853 
1854 	const auto fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderInfo);
1855 
1856 	// Vertex input state (common, but should be unused by the mesh shading pipeline).
1857 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo		= initVulkanStructure();
1858 	VkPipelineInputAssemblyStateCreateInfo		inputAssemblyStateCreateInfo	= initVulkanStructure();
1859 	inputAssemblyStateCreateInfo.topology										= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1860 	const auto									vertexInputLibInfo				= makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
1861 
1862 	VkGraphicsPipelineCreateInfo vertexInputInfo	= initVulkanStructure();
1863 	vertexInputInfo.layout							= pipelineLayout.get();
1864 	vertexInputInfo.pVertexInputState				= &vertexInputStateCreateInfo;
1865 	vertexInputInfo.pInputAssemblyState				= &inputAssemblyStateCreateInfo;
1866 	vertexInputInfo.flags							= libCompileFlags;
1867 	vertexInputInfo.pNext							= &vertexInputLibInfo;
1868 
1869 	const auto vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputInfo);
1870 
1871 	// Pre-rasterization shader state: common pieces.
1872 	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
1873 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
1874 
1875 	const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
1876 	{
1877 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	//	VkStructureType						sType;
1878 		nullptr,												//	const void*							pNext;
1879 		0u,														//	VkPipelineViewportStateCreateFlags	flags;
1880 		static_cast<uint32_t>(viewports.size()),				//	uint32_t							viewportCount;
1881 		de::dataOrNull(viewports),								//	const VkViewport*					pViewports;
1882 		static_cast<uint32_t>(scissors.size()),					//	uint32_t							scissorCount;
1883 		de::dataOrNull(scissors),								//	const VkRect2D*						pScissors;
1884 	};
1885 
1886 	const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
1887 	{
1888 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//	VkStructureType							sType;
1889 		nullptr,														//	const void*								pNext;
1890 		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
1891 		VK_FALSE,														//	VkBool32								depthClampEnable;
1892 		VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
1893 		VK_POLYGON_MODE_FILL,											//	VkPolygonMode							polygonMode;
1894 		VK_CULL_MODE_NONE,												//	VkCullModeFlags							cullMode;
1895 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								//	VkFrontFace								frontFace;
1896 		VK_FALSE,														//	VkBool32								depthBiasEnable;
1897 		0.0f,															//	float									depthBiasConstantFactor;
1898 		0.0f,															//	float									depthBiasClamp;
1899 		0.0f,															//	float									depthBiasSlopeFactor;
1900 		1.0f,															//	float									lineWidth;
1901 	};
1902 
1903 	const auto preRastLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1904 
1905 	VkGraphicsPipelineCreateInfo preRastShaderInfo	= initVulkanStructure();
1906 	preRastShaderInfo.layout						= pipelineLayout.get();
1907 	preRastShaderInfo.pViewportState				= &viewportStateCreateInfo;
1908 	preRastShaderInfo.pRasterizationState			= &rasterizationStateCreateInfo;
1909 	preRastShaderInfo.renderPass					= renderPass.get();
1910 	preRastShaderInfo.flags							= libCompileFlags;
1911 	preRastShaderInfo.pNext							= &preRastLibInfo;
1912 	preRastShaderInfo.stageCount					= 1u;
1913 
1914 	// Vertex stage info.
1915 	const VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo =
1916 	{
1917 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
1918 		nullptr,												//	const void*							pNext;
1919 		0u,														//	VkPipelineShaderStageCreateFlags	flags;
1920 		VK_SHADER_STAGE_VERTEX_BIT,								//	VkShaderStageFlagBits				stage;
1921 		vertModule.get(),										//	VkShaderModule						module;
1922 		"main",													//	const char*							pName;
1923 		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
1924 	};
1925 
1926 	// Mesh stage info.
1927 	const VkPipelineShaderStageCreateInfo meshShaderStageCreateInfo =
1928 	{
1929 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
1930 		nullptr,												//	const void*							pNext;
1931 		0u,														//	VkPipelineShaderStageCreateFlags	flags;
1932 		VK_SHADER_STAGE_MESH_BIT_EXT,							//	VkShaderStageFlagBits				stage;
1933 		meshModule.get(),										//	VkShaderModule						module;
1934 		"main",													//	const char*							pName;
1935 		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
1936 	};
1937 
1938 	// Pre-rasterization shader libs.
1939 	preRastShaderInfo.pStages = &vertShaderStageCreateInfo;
1940 	const auto preRastClassicLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRastShaderInfo);
1941 
1942 	preRastShaderInfo.pStages = &meshShaderStageCreateInfo;
1943 	const auto preRastMeshLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRastShaderInfo);
1944 
1945 	// Pipelines.
1946 	const std::vector<VkPipeline> classicLibs	{ vertexInputLib.get(), preRastClassicLib.get(),	fragShaderLib.get(), fragOutputLib.get() };
1947 	const std::vector<VkPipeline> meshLibs		{ vertexInputLib.get(), preRastMeshLib.get(),		fragShaderLib.get(), fragOutputLib.get() };
1948 
1949 	const VkPipelineLibraryCreateInfoKHR classicLinkInfo =
1950 	{
1951 		VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,	//	VkStructureType		sType;
1952 		nullptr,											//	const void*			pNext;
1953 		static_cast<uint32_t>(classicLibs.size()),			//	uint32_t			libraryCount;
1954 		de::dataOrNull(classicLibs),						//	const VkPipeline*	pLibraries;
1955 	};
1956 
1957 	const VkPipelineLibraryCreateInfoKHR meshLinkInfo =
1958 	{
1959 		VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,	//	VkStructureType		sType;
1960 		nullptr,											//	const void*			pNext;
1961 		static_cast<uint32_t>(meshLibs.size()),				//	uint32_t			libraryCount;
1962 		de::dataOrNull(meshLibs),							//	const VkPipeline*	pLibraries;
1963 	};
1964 
1965 	VkGraphicsPipelineCreateInfo classicPipelineCreateInfo = initVulkanStructure();
1966 	classicPipelineCreateInfo.flags		= pipelineLinkFlags;
1967 	classicPipelineCreateInfo.layout	= pipelineLayout.get();
1968 	classicPipelineCreateInfo.pNext		= &classicLinkInfo;
1969 
1970 	VkGraphicsPipelineCreateInfo meshPipelineCreateInfo = initVulkanStructure();
1971 	meshPipelineCreateInfo.flags	= pipelineLinkFlags;
1972 	meshPipelineCreateInfo.layout	= pipelineLayout.get();
1973 	meshPipelineCreateInfo.pNext	= &meshLinkInfo;
1974 
1975 	const auto classicPipeline	= createGraphicsPipeline(vkd, device, DE_NULL, &classicPipelineCreateInfo);
1976 	const auto meshPipeline		= createGraphicsPipeline(vkd, device, DE_NULL, &meshPipelineCreateInfo);
1977 
1978 	// Record commands with both pipelines.
1979 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
1980 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1981 	const auto cmdBuffer	= cmdBufferPtr.get();
1982 
1983 	beginCommandBuffer(vkd, cmdBuffer);
1984 
1985 	// Draw using both pipelines.
1986 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
1987 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, classicPipeline.get());
1988 	vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1989 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, meshPipeline.get());
1990 	vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
1991 	endRenderPass(vkd, cmdBuffer);
1992 
1993 	// Copy color buffer to verification buffer.
1994 	const auto preTransferBarrier = makeImageMemoryBarrier(
1995 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1996 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1997 		colorBuffer.get(), colorBufferSRR);
1998 
1999 	const auto postTransferBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2000 
2001 	const auto copyRegion = makeBufferImageCopy(fbExtent, colorBufferSRL);
2002 
2003 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preTransferBarrier);
2004 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2005 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postTransferBarrier);
2006 
2007 	endCommandBuffer(vkd, cmdBuffer);
2008 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2009 
2010 	// Validate color buffer.
2011 	invalidateAlloc(vkd, device, verificationBufferAlloc);
2012 
2013 	tcu::ConstPixelBufferAccess	resultAccess	(tcuFormat, iExtent, verificationBufferData);
2014 	auto&						log				= m_context.getTestContext().getLog();
2015 	bool						fail			= false;
2016 
2017 	for (int z = 0; z < iExtent.z(); ++z)
2018 	{
2019 		const auto& expectedColor = layerColors.at(z);
2020 		for (int y = 0; y < iExtent.y(); ++y)
2021 			for (int x = 0; x < iExtent.x(); ++x)
2022 			{
2023 				const auto resultColor = resultAccess.getPixel(x, y, z);
2024 				if (resultColor != expectedColor)
2025 				{
2026 					std::ostringstream msg;
2027 					msg << "Unexpected color at coordinates (x=" << x << ", y=" << y << ", layer=" << z << "): expected " << expectedColor << " but found " << resultColor;
2028 					log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2029 					fail = true;
2030 				}
2031 			}
2032 	}
2033 
2034 	if (fail)
2035 		return tcu::TestStatus::fail("Failed; check log for details");
2036 	return tcu::TestStatus::pass("Pass");
2037 }
2038 
2039 } // anonymous namespace
2040 
createMeshShaderSmokeTestsEXT(tcu::TestContext & testCtx)2041 tcu::TestCaseGroup* createMeshShaderSmokeTestsEXT (tcu::TestContext& testCtx)
2042 {
2043 	struct
2044 	{
2045 		PipelineConstructionType	constructionType;
2046 		const char*					name;
2047 	} constructionTypes[] =
2048 	{
2049 		{ PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC,					"monolithic"		},
2050 		{ PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY,	"optimized_lib"		},
2051 		{ PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY,			"fast_lib"			},
2052 	};
2053 
2054 	GroupPtr smokeTests (new tcu::TestCaseGroup(testCtx, "smoke"));
2055 
2056 	for (const auto& constructionCase : constructionTypes)
2057 	{
2058 		GroupPtr constructionGroup(new tcu::TestCaseGroup(testCtx, constructionCase.name));
2059 
2060 		const auto& cType = constructionCase.constructionType;
2061 
2062 		constructionGroup->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle", cType));
2063 		constructionGroup->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle_rasterization_disabled", cType, true/*rasterizationDisabled*/));
2064 		constructionGroup->addChild(new MeshTaskTriangleCase(testCtx, "mesh_task_shader_triangle", cType));
2065 		constructionGroup->addChild(new TaskOnlyTriangleCase(testCtx, "task_only_shader_triangle", cType));
2066 
2067 		for (int i = 0; i < 2; ++i)
2068 		{
2069 			const bool					compaction	= (i == 0);
2070 			const std::string			nameSuffix	= (compaction ? "" : "_without_compaction");
2071 			const PartialUsageParams	params		{ cType, compaction };
2072 
2073 			constructionGroup->addChild(new PartialUsageCase(testCtx, "partial_usage" + nameSuffix, params));
2074 		}
2075 
2076 		addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient",			checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::nothing<FragmentSize>(), cType));
2077 		addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient_fs2x2",	checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::just(FragmentSize::SIZE_2X2), cType));
2078 		addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient_fs2x1",	checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::just(FragmentSize::SIZE_2X1), cType));
2079 
2080 		if (cType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2081 		{
2082 			constructionGroup->addChild(new SharedFragLibraryCase(testCtx, "shared_frag_library", cType));
2083 		}
2084 
2085 		smokeTests->addChild(constructionGroup.release());
2086 	}
2087 
2088 	return smokeTests.release();
2089 }
2090 
2091 } // MeshShader
2092 } // vkt
2093