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