1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 LunarG, Inc.
6  * Copyright (c) 2023 Nintendo
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 Shader Object Link Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vktShaderObjectCreateUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deRandom.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 
37 namespace vkt
38 {
39 namespace ShaderObject
40 {
41 
42 namespace
43 {
44 
45 enum ShaderType {
46 	UNUSED,
47 	LINKED,
48 	UNLINKED,
49 };
50 
51 struct Shaders {
52 	ShaderType	vertex;
53 	ShaderType	tesellation_control;
54 	ShaderType	tesellation_evaluation;
55 	ShaderType	geometry;
56 	ShaderType	fragment;
57 };
58 
59 struct MeshShaders {
60 	ShaderType	task;
61 	ShaderType	mesh;
62 	ShaderType	fragment;
63 };
64 
65 struct NextStages {
66 	vk::VkShaderStageFlags	vertNextStage;
67 	vk::VkShaderStageFlags	tescNextStage;
68 	vk::VkShaderStageFlags	teseNextStage;
69 	vk::VkShaderStageFlags	geomNextStage;
70 };
71 
72 struct MeshNextStages {
73 	vk::VkShaderStageFlags	taskNextStage;
74 	vk::VkShaderStageFlags	meshNextStage;
75 };
76 
77 enum BindType {
78 	SEPARATE,
79 	ONE_LINKED_UNLINKED,
80 	ALL,
81 };
82 
83 struct TestParams {
84 	Shaders		shaders;
85 	bool		randomOrder;
86 	NextStages	nextStages;
87 	bool		separateLinked;
88 	BindType	separateBind;
89 };
90 
91 struct MeshParams {
92 	MeshShaders		shaders;
93 	bool			randomOrder;
94 	MeshNextStages	nextStages;
95 };
96 
97 class ShaderObjectLinkInstance : public vkt::TestInstance
98 {
99 public:
ShaderObjectLinkInstance(Context& context, const TestParams& params)100 							ShaderObjectLinkInstance	(Context& context, const TestParams& params)
101 														: vkt::TestInstance	(context)
102 														, m_params			(params)
103 														{}
~ShaderObjectLinkInstance(void)104 	virtual					~ShaderObjectLinkInstance	(void) {}
105 
106 	tcu::TestStatus			iterate						(void) override;
107 private:
108 	vk::VkShaderStageFlags	getNextStage				(vk::VkShaderStageFlagBits currentStage);
109 
110 	TestParams m_params;
111 };
112 
getNextStage(vk::VkShaderStageFlagBits currentStage)113 vk::VkShaderStageFlags ShaderObjectLinkInstance::getNextStage (vk::VkShaderStageFlagBits currentStage)
114 {
115 	if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT && m_params.shaders.vertex == LINKED)
116 	{
117 		if (m_params.shaders.tesellation_control != UNUSED)
118 		{
119 			if (m_params.shaders.tesellation_control == LINKED)
120 				return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
121 		}
122 		else if (m_params.shaders.geometry != UNUSED)
123 		{
124 			if (m_params.shaders.geometry == LINKED)
125 				return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
126 		}
127 		else if (m_params.shaders.fragment != UNUSED)
128 		{
129 			if (m_params.shaders.fragment == LINKED)
130 				return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
131 		}
132 	}
133 	else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT && m_params.shaders.tesellation_control == LINKED && m_params.shaders.tesellation_evaluation == LINKED)
134 	{
135 		return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
136 	}
137 	else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT && m_params.shaders.tesellation_evaluation == LINKED)
138 	{
139 		if (m_params.shaders.geometry != UNUSED)
140 		{
141 			if (m_params.shaders.geometry == LINKED)
142 				return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
143 		}
144 		else if (m_params.shaders.fragment != UNUSED)
145 		{
146 			if (m_params.shaders.fragment == LINKED)
147 				return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
148 		}
149 	}
150 	else if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT && m_params.shaders.geometry == LINKED)
151 	{
152 		if (m_params.shaders.fragment != UNUSED)
153 		{
154 			if (m_params.shaders.fragment == LINKED)
155 				return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
156 		}
157 	}
158 
159 	if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
160 		return m_params.nextStages.vertNextStage;
161 
162 	if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
163 		return m_params.nextStages.tescNextStage;
164 
165 	if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
166 		return m_params.nextStages.teseNextStage;
167 
168 	if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
169 		return m_params.nextStages.geomNextStage;
170 
171 	return 0;
172 }
173 
iterate(void)174 tcu::TestStatus ShaderObjectLinkInstance::iterate (void)
175 {
176 	const vk::VkInstance				instance					= m_context.getInstance();
177 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
178 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
179 	const vk::VkDevice					device						= m_context.getDevice();
180 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
181 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
182 	auto&								alloc						= m_context.getDefaultAllocator();
183 	tcu::TestLog&						log							= m_context.getTestContext().getLog();
184 	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
185 	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
186 	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
187 	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
188 	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
189 
190 	vk::VkFormat						colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
191 	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
192 
193 	const vk::VkImageCreateInfo	createInfo =
194 	{
195 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
196 		DE_NULL,									// const void*				pNext
197 		0u,											// VkImageCreateFlags		flags
198 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
199 		colorAttachmentFormat,						// VkFormat					format
200 		{ 32, 32, 1 },								// VkExtent3D				extent
201 		1u,											// uint32_t					mipLevels
202 		1u,											// uint32_t					arrayLayers
203 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
204 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
205 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
206 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
207 		0,											// uint32_t					queueFamilyIndexCount
208 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
209 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
210 	};
211 
212 	de::MovePtr<vk::ImageWithMemory>	image					= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
213 	const auto							imageView				= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
214 	const vk::VkRect2D					renderArea				= vk::makeRect2D(0, 0, 32, 32);
215 
216 	const vk::VkDeviceSize				colorOutputBufferSize	= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
217 	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer		= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
218 		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
219 
220 	const auto&					binaries			= m_context.getBinaryCollection();
221 	const auto&					vert				= binaries.get("vert");
222 	const auto&					tesc				= binaries.get("tesc");
223 	const auto&					tese				= binaries.get("tese");
224 	const auto&					geom				= binaries.get("geom");
225 	const auto&					frag				= binaries.get("frag");
226 
227 	vk::VkShaderEXT				vertShader;
228 	vk::VkShaderEXT				tescShader;
229 	vk::VkShaderEXT				teseShader;
230 	vk::VkShaderEXT				geomShader;
231 	vk::VkShaderEXT				fragShader;
232 
233 	std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
234 
235 	vk::VkShaderCreateInfoEXT	vertShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert, tessellationSupported, geometrySupported);
236 	vertShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_VERTEX_BIT);
237 
238 	if (m_params.shaders.vertex == LINKED)
239 	{
240 		vertShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
241 		shaderCreateInfos.push_back(vertShaderCreateInfo);
242 	}
243 	else if (m_params.shaders.vertex == UNLINKED)
244 	{
245 		vk.createShadersEXT(device, 1, &vertShaderCreateInfo, DE_NULL, &vertShader);
246 	}
247 
248 	vk::VkShaderCreateInfoEXT tescShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported);
249 	tescShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
250 
251 	if (m_params.shaders.tesellation_control == LINKED)
252 	{
253 		tescShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
254 		shaderCreateInfos.push_back(tescShaderCreateInfo);
255 	}
256 	else if (m_params.shaders.tesellation_control == UNLINKED)
257 	{
258 		vk.createShadersEXT(device, 1, &tescShaderCreateInfo, DE_NULL, &tescShader);
259 	}
260 
261 	vk::VkShaderCreateInfoEXT teseShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported);
262 	teseShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
263 
264 	if (m_params.shaders.tesellation_evaluation == LINKED)
265 	{
266 		teseShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
267 		shaderCreateInfos.push_back(teseShaderCreateInfo);
268 	}
269 	else if (m_params.shaders.tesellation_evaluation == UNLINKED)
270 	{
271 		vk.createShadersEXT(device, 1, &teseShaderCreateInfo, DE_NULL, &teseShader);
272 	}
273 
274 	vk::VkShaderCreateInfoEXT geomShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported);
275 	geomShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
276 
277 	if (m_params.shaders.geometry == LINKED)
278 	{
279 		geomShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
280 		shaderCreateInfos.push_back(geomShaderCreateInfo);
281 	}
282 	else if (m_params.shaders.geometry == UNLINKED)
283 	{
284 		vk.createShadersEXT(device, 1, &geomShaderCreateInfo, DE_NULL, &geomShader);
285 	}
286 
287 	vk::VkShaderCreateInfoEXT fragShaderCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag, tessellationSupported, geometrySupported);
288 	fragShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
289 
290 	if (m_params.shaders.fragment == LINKED)
291 	{
292 		fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
293 		shaderCreateInfos.push_back(fragShaderCreateInfo);
294 	}
295 	else if (m_params.shaders.fragment == UNLINKED)
296 	{
297 		vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
298 	}
299 
300 	vk::VkPrimitiveTopology			primitiveTopology		= m_params.shaders.tesellation_control != UNUSED ?
301 																vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
302 																vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
303 
304 	if (!shaderCreateInfos.empty())
305 	{
306 		std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
307 		deUint32 i = 0u;
308 		deUint32 j = 0u;
309 		if (m_params.randomOrder && shaderCreateInfos.size() > 1)
310 		{
311 			de::Random random(102030);
312 			i = random.getUint32() % (deUint32)shaders.size();
313 			do {
314 				j = random.getUint32() % (deUint32)shaders.size();
315 			} while (i == j);
316 			std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
317 		}
318 		if (m_params.separateLinked)
319 		{
320 			for (deUint32 k = 0; k < (deUint32)shaders.size(); ++k)
321 				vk.createShadersEXT(device, 1u, &shaderCreateInfos[k], DE_NULL, &shaders[k]);
322 		}
323 		else
324 		{
325 			vk.createShadersEXT(device, (deUint32)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
326 		}
327 		if (m_params.randomOrder && shaderCreateInfos.size() > 1)
328 		{
329 			std::swap(shaders[i], shaders[j]);
330 		}
331 		deUint32 n = 0;
332 		if (m_params.shaders.vertex == LINKED)
333 		{
334 			vertShader = shaders[n++];
335 		}
336 		if (m_params.shaders.tesellation_control == LINKED)
337 		{
338 			tescShader = shaders[n++];
339 		}
340 		if (m_params.shaders.tesellation_evaluation == LINKED)
341 		{
342 			teseShader = shaders[n++];
343 		}
344 		if (m_params.shaders.geometry == LINKED)
345 		{
346 			geomShader = shaders[n++];
347 		}
348 		if (m_params.shaders.fragment == LINKED)
349 		{
350 			fragShader = shaders[n++];
351 		}
352 	}
353 
354 	const vk::VkCommandPoolCreateInfo	cmdPoolInfo =
355 	{
356 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType
357 		DE_NULL,												// pNext
358 		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags
359 		queueFamilyIndex,										// queuefamilyindex
360 	};
361 
362 	const vk::Move<vk::VkCommandPool>	cmdPool		(createCommandPool(vk, device, &cmdPoolInfo));
363 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
364 
365 	// Draw
366 	vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
367 
368 	vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
369 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
370 
371 	if (m_params.separateBind == SEPARATE)
372 	{
373 		vk::VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
374 		vk::VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
375 		vk::VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
376 		vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
377 		vk::VkShaderStageFlagBits fragStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
378 		vk::VkShaderEXT bindVertShader = (m_params.shaders.vertex != UNUSED) ? vertShader : VK_NULL_HANDLE;
379 		vk::VkShaderEXT bindTescShader = (m_params.shaders.tesellation_control != UNUSED) ? tescShader : VK_NULL_HANDLE;
380 		vk::VkShaderEXT bindTeseShader = (m_params.shaders.tesellation_evaluation!= UNUSED) ? teseShader : VK_NULL_HANDLE;
381 		vk::VkShaderEXT bindGeomShader = (m_params.shaders.geometry != UNUSED) ? geomShader : VK_NULL_HANDLE;
382 		vk::VkShaderEXT bindFragShader = (m_params.shaders.fragment != UNUSED) ? fragShader : VK_NULL_HANDLE;
383 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &vertStage, &bindVertShader);
384 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &tescStage, &bindTescShader);
385 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &teseStage, &bindTeseShader);
386 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &bindGeomShader);
387 		vk.cmdBindShadersEXT(*cmdBuffer, 1u, &fragStage, &bindFragShader);
388 	}
389 	else if (m_params.separateBind == ONE_LINKED_UNLINKED)
390 	{
391 		std::vector<vk::VkShaderStageFlagBits>	separateStages;
392 		std::vector<vk::VkShaderStageFlagBits>	togetherStages;
393 		std::vector<vk::VkShaderEXT>			separateShaders;
394 		std::vector<vk::VkShaderEXT>			togetherShaders;
395 
396 		bool linkedAdded = false;
397 		if ((!linkedAdded && m_params.shaders.vertex == LINKED) || m_params.shaders.vertex == UNLINKED)
398 		{
399 			togetherStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
400 			togetherShaders.push_back(vertShader);
401 			linkedAdded = true;
402 		}
403 		else if (m_params.shaders.vertex == LINKED)
404 		{
405 			separateStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
406 			togetherShaders.push_back(vertShader);
407 		}
408 
409 		if ((!linkedAdded && m_params.shaders.tesellation_control == LINKED) || m_params.shaders.tesellation_control == UNLINKED)
410 		{
411 			togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
412 			togetherShaders.push_back(tescShader);
413 			linkedAdded = true;
414 		}
415 		else if (m_params.shaders.tesellation_control == LINKED)
416 		{
417 			separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
418 			separateShaders.push_back(tescShader);
419 		}
420 
421 		if ((!linkedAdded && m_params.shaders.tesellation_evaluation == LINKED) || m_params.shaders.tesellation_evaluation == UNLINKED)
422 		{
423 			togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
424 			togetherShaders.push_back(teseShader);
425 			linkedAdded = true;
426 		}
427 		else if (m_params.shaders.tesellation_evaluation == LINKED)
428 		{
429 			separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
430 			separateShaders.push_back(teseShader);
431 		}
432 
433 		if ((!linkedAdded && m_params.shaders.geometry == LINKED) || m_params.shaders.geometry == UNLINKED)
434 		{
435 			togetherStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
436 			togetherShaders.push_back(geomShader);
437 			linkedAdded = true;
438 		}
439 		else if (m_params.shaders.geometry == LINKED)
440 		{
441 			separateStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
442 			separateShaders.push_back(geomShader);
443 		}
444 
445 		if ((!linkedAdded && m_params.shaders.fragment == LINKED) || m_params.shaders.fragment == UNLINKED)
446 		{
447 			togetherStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
448 			togetherShaders.push_back(fragShader);
449 			linkedAdded = true;
450 		}
451 		else if (m_params.shaders.fragment == LINKED)
452 		{
453 			separateStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
454 			separateShaders.push_back(fragShader);
455 		}
456 
457 		vk::bindGraphicsShaders(vk, *cmdBuffer, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, taskSupported, meshSupported);
458 		if (!togetherShaders.empty())
459 			vk.cmdBindShadersEXT(*cmdBuffer, (deUint32)togetherShaders.size(), togetherStages.data(), togetherShaders.data());
460 		if (!separateShaders.empty())
461 			vk.cmdBindShadersEXT(*cmdBuffer, (deUint32)separateShaders.size(), separateStages.data(), separateShaders.data());
462 	}
463 	else
464 	{
465 		vk::bindGraphicsShaders(vk, *cmdBuffer,
466 			m_params.shaders.vertex != UNUSED ? vertShader : VK_NULL_HANDLE,
467 			m_params.shaders.tesellation_control != UNUSED ? tescShader : VK_NULL_HANDLE,
468 			m_params.shaders.tesellation_evaluation != UNUSED ? teseShader : VK_NULL_HANDLE,
469 			m_params.shaders.geometry != UNUSED ? geomShader : VK_NULL_HANDLE,
470 			m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE,
471 			taskSupported,
472 			meshSupported);
473 	}
474 	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, primitiveTopology, false);
475 
476 	bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
477 
478 	const vk::VkClearValue				clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
479 	vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
480 	vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
481 	vk::endRendering(vk, *cmdBuffer);
482 
483 	vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
484 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
485 
486 	const vk::VkBufferImageCopy	copyRegion =
487 	{
488 		0u,																		// VkDeviceSize				bufferOffset;
489 		0u,																		// deUint32					bufferRowLength;
490 		0u,																		// deUint32					bufferImageHeight;
491 		{
492 			vk::VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags		aspect;
493 			0u,																	// deUint32					mipLevel;
494 			0u,																	// deUint32					baseArrayLayer;
495 			1u,																	// deUint32					layerCount;
496 		},																		// VkImageSubresourceLayers	imageSubresource;
497 		{ 0, 0, 0 },															// VkOffset3D				imageOffset;
498 		{renderArea.extent.width, renderArea.extent.height, 1}					// VkExtent3D				imageExtent;
499 	};
500 	vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
501 
502 	vk::endCommandBuffer(vk, *cmdBuffer);
503 
504 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
505 
506 	// Cleanup
507 	if (m_params.shaders.vertex != UNUSED)
508 		vk.destroyShaderEXT(device, vertShader, DE_NULL);
509 
510 	if (m_params.shaders.tesellation_control != UNUSED)
511 		vk.destroyShaderEXT(device, tescShader, DE_NULL);
512 
513 	if (m_params.shaders.tesellation_evaluation != UNUSED)
514 		vk.destroyShaderEXT(device, teseShader, DE_NULL);
515 
516 	if (m_params.shaders.geometry != UNUSED)
517 		vk.destroyShaderEXT(device, geomShader, DE_NULL);
518 
519 	if (m_params.shaders.fragment != UNUSED)
520 		vk.destroyShaderEXT(device, fragShader, DE_NULL);
521 
522 	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
523 
524 	const tcu::Vec4			black		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
525 	const tcu::Vec4			white		= tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
526 	const deInt32			width		= resultBuffer.getWidth();
527 	const deInt32			height		= resultBuffer.getHeight();
528 	const deInt32			xOffset		= m_params.shaders.tesellation_control != UNUSED ? 4 : 8;
529 	const deInt32			yOffset		= m_params.shaders.geometry != UNUSED ? 4 : 8;
530 
531 	for (deInt32 j = 0; j < height; ++j)
532 	{
533 		for (deInt32 i = 0; i < width; ++i)
534 		{
535 			const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
536 			if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
537 			{
538 				if (color != white)
539 				{
540 					log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
541 					return tcu::TestStatus::fail("Fail");
542 				}
543 			}
544 			else
545 			{
546 				if (color != black)
547 				{
548 					log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (0.0, 0.0, 0.0, 0.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
549 					return tcu::TestStatus::fail("Fail");
550 				}
551 			}
552 		}
553 	}
554 
555 	return tcu::TestStatus::pass("Pass");
556 }
557 
558 class ShaderObjectLinkCase : public vkt::TestCase
559 {
560 public:
ShaderObjectLinkCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)561 							ShaderObjectLinkCase	(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
562 													: vkt::TestCase		(testCtx, name)
563 													, m_params			(params)
564 													{}
~ShaderObjectLinkCase(void)565 	virtual					~ShaderObjectLinkCase	(void) {}
566 
567 	void					checkSupport			(vkt::Context& context) const override;
568 	virtual void			initPrograms			(vk::SourceCollections& programCollection) const override;
569 	TestInstance*			createInstance			(Context& context) const override { return new ShaderObjectLinkInstance(context, m_params); }
570 private:
571 	TestParams m_params;
572 };
573 
checkSupport(Context& context) const574 void ShaderObjectLinkCase::checkSupport (Context& context) const
575 {
576 	context.requireDeviceFunctionality("VK_EXT_shader_object");
577 
578 	if (m_params.shaders.tesellation_control != UNUSED || m_params.shaders.tesellation_evaluation != UNUSED
579 		|| (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) > 0)
580 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
581 
582 	if (m_params.shaders.geometry != UNUSED
583 		|| (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0
584 		|| (m_params.nextStages.teseNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0)
585 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
586 }
587 
initPrograms(vk::SourceCollections& programCollection) const588 void ShaderObjectLinkCase::initPrograms (vk::SourceCollections& programCollection) const
589 {
590 	vk::addBasicShaderObjectShaders(programCollection);
591 }
592 
593 
594 class MeshShaderObjectLinkInstance : public vkt::TestInstance
595 {
596 public:
MeshShaderObjectLinkInstance(Context& context, const MeshParams& params)597 							MeshShaderObjectLinkInstance	(Context& context, const MeshParams& params)
598 															: vkt::TestInstance	(context)
599 															, m_params			(params)
600 															{}
~MeshShaderObjectLinkInstance(void)601 	virtual					~MeshShaderObjectLinkInstance	(void) {}
602 
603 	tcu::TestStatus			iterate							(void) override;
604 private:
605 	vk::VkShaderStageFlags	getNextStage					(vk::VkShaderStageFlagBits currentStage);
606 
607 	MeshParams m_params;
608 };
609 
getNextStage(vk::VkShaderStageFlagBits currentStage)610 vk::VkShaderStageFlags MeshShaderObjectLinkInstance::getNextStage (vk::VkShaderStageFlagBits currentStage)
611 {
612 	if (currentStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
613 	{
614 		if (m_params.shaders.task == LINKED)
615 			return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
616 		return m_params.nextStages.taskNextStage;
617 	}
618 
619 	if (currentStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
620 	{
621 		if (m_params.shaders.mesh == LINKED)
622 			return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
623 		return m_params.nextStages.meshNextStage;
624 	}
625 
626 	return 0;
627 }
628 
iterate(void)629 tcu::TestStatus MeshShaderObjectLinkInstance::iterate (void)
630 {
631 	const vk::VkInstance				instance					= m_context.getInstance();
632 	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
633 	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
634 	const vk::VkDevice					device						= m_context.getDevice();
635 	const vk::VkQueue					queue						= m_context.getUniversalQueue();
636 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
637 	auto&								alloc						= m_context.getDefaultAllocator();
638 	tcu::TestLog&						log							= m_context.getTestContext().getLog();
639 	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
640 
641 	vk::VkFormat						colorAttachmentFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
642 	const auto							subresourceRange			= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
643 
644 	const vk::VkImageCreateInfo	createInfo =
645 	{
646 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
647 		DE_NULL,									// const void*				pNext
648 		0u,											// VkImageCreateFlags		flags
649 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
650 		colorAttachmentFormat,						// VkFormat					format
651 		{ 32, 32, 1 },								// VkExtent3D				extent
652 		1u,											// uint32_t					mipLevels
653 		1u,											// uint32_t					arrayLayers
654 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
655 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
656 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
657 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
658 		0,											// uint32_t					queueFamilyIndexCount
659 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
660 		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
661 	};
662 
663 	de::MovePtr<vk::ImageWithMemory>	image					= de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
664 	const auto							imageView				= vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
665 	const vk::VkRect2D					renderArea				= vk::makeRect2D(0, 0, 32, 32);
666 
667 	const vk::VkDeviceSize				colorOutputBufferSize	= renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
668 	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer		= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
669 		vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
670 
671 	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
672 		vk::DescriptorSetLayoutBuilder()
673 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_MESH_BIT_EXT)
674 		.build(vk, device));
675 
676 	const vk::Unique<vk::VkDescriptorPool> descriptorPool(
677 		vk::DescriptorPoolBuilder()
678 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
679 		.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
680 
681 	const vk::VkDeviceSize					bufferSizeBytes = sizeof(deUint32) * 4;
682 	const vk::Unique<vk::VkDescriptorSet>	descriptorSet	(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
683 	const vk::BufferWithMemory				outputBuffer	(vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
684 
685 	const vk::VkDescriptorBufferInfo		descriptorInfo	= vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
686 	vk::DescriptorSetUpdateBuilder()
687 		.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
688 		.update(vk, device);
689 
690 	const auto								pipelineLayout	= makePipelineLayout(vk, device, *descriptorSetLayout);
691 
692 	const auto&					binaries			= m_context.getBinaryCollection();
693 	const auto&					task				= binaries.get("task");
694 	const auto&					mesh				= binaries.get("mesh");
695 	const auto&					frag				= binaries.get("frag");
696 
697 	vk::VkShaderEXT				taskShader;
698 	vk::VkShaderEXT				meshShader;
699 	vk::VkShaderEXT				fragShader;
700 
701 	std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
702 
703 	vk::VkShaderCreateInfoEXT taskShaderCreateInfo =
704 	{
705 		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
706 		DE_NULL,										// const void*					pNext;
707 		0u,												// VkShaderCreateFlagsEXT		flags;
708 		vk::VK_SHADER_STAGE_TASK_BIT_EXT,				// VkShaderStageFlagBits		stage;
709 		getNextStage(vk::VK_SHADER_STAGE_TASK_BIT_EXT),	// VkShaderStageFlags			nextStage;
710 		vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
711 		task.getSize(),									// size_t						codeSize;
712 		task.getBinary(),								// const void*					pCode;
713 		"main",											// const char*					pName;
714 		1u,												// uint32_t						setLayoutCount;
715 		&*descriptorSetLayout,							// VkDescriptorSetLayout*		pSetLayouts;
716 		0u,												// uint32_t						pushConstantRangeCount;
717 		DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
718 		DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
719 	};
720 
721 	if (m_params.shaders.task == LINKED)
722 	{
723 		taskShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
724 		shaderCreateInfos.push_back(taskShaderCreateInfo);
725 	}
726 	else if (m_params.shaders.task == UNLINKED)
727 	{
728 		vk.createShadersEXT(device, 1, &taskShaderCreateInfo, DE_NULL, &taskShader);
729 	}
730 
731 	vk::VkShaderCreateInfoEXT meshShaderCreateInfo =
732 	{
733 		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,				// VkStructureType				sType;
734 		DE_NULL,													// const void*					pNext;
735 		(m_params.shaders.task == UNUSED) ? (vk::VkShaderCreateFlagsEXT)vk::VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT : (vk::VkShaderCreateFlagsEXT)0u,
736 																	// VkShaderCreateFlagsEXT		flags;
737 		vk::VK_SHADER_STAGE_MESH_BIT_EXT,							// VkShaderStageFlagBits		stage;
738 		getNextStage(vk::VK_SHADER_STAGE_MESH_BIT_EXT),				// VkShaderStageFlags			nextStage;
739 		vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,							// VkShaderCodeTypeEXT			codeType;
740 		mesh.getSize(),												// size_t						codeSize;
741 		mesh.getBinary(),											// const void*					pCode;
742 		"main",														// const char*					pName;
743 		1u,															// uint32_t						setLayoutCount;
744 		&*descriptorSetLayout,										// VkDescriptorSetLayout*		pSetLayouts;
745 		0u,															// uint32_t						pushConstantRangeCount;
746 		DE_NULL,													// const VkPushConstantRange*	pPushConstantRanges;
747 		DE_NULL,													// const VkSpecializationInfo*	pSpecializationInfo;
748 	};
749 
750 	if (m_params.shaders.mesh == LINKED)
751 	{
752 		meshShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
753 		shaderCreateInfos.push_back(meshShaderCreateInfo);
754 	}
755 	else if (m_params.shaders.mesh == UNLINKED)
756 	{
757 		vk.createShadersEXT(device, 1, &meshShaderCreateInfo, DE_NULL, &meshShader);
758 	}
759 
760 	vk::VkShaderCreateInfoEXT fragShaderCreateInfo =
761 	{
762 		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
763 		DE_NULL,										// const void*					pNext;
764 		0u,												// VkShaderCreateFlagsEXT		flags;
765 		vk::VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlagBits		stage;
766 		getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT),	// VkShaderStageFlags			nextStage;
767 		vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
768 		frag.getSize(),									// size_t						codeSize;
769 		frag.getBinary(),								// const void*					pCode;
770 		"main",											// const char*					pName;
771 		1u,												// uint32_t						setLayoutCount;
772 		&*descriptorSetLayout,							// VkDescriptorSetLayout*		pSetLayouts;
773 		0u,												// uint32_t						pushConstantRangeCount;
774 		DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
775 		DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
776 	};
777 
778 	if (m_params.shaders.fragment == LINKED)
779 	{
780 		fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
781 		shaderCreateInfos.push_back(fragShaderCreateInfo);
782 	}
783 	else if (m_params.shaders.fragment == UNLINKED)
784 	{
785 		vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
786 	}
787 
788 	if (!shaderCreateInfos.empty())
789 	{
790 		std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
791 		deUint32 i = 0u;
792 		deUint32 j = 0u;
793 		if (m_params.randomOrder && shaderCreateInfos.size() > 1)
794 		{
795 			de::Random random(102030);
796 			i = random.getUint32() % (deUint32)shaders.size();
797 			do {
798 				j = random.getUint32() % (deUint32)shaders.size();
799 			} while (i == j);
800 			std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
801 		}
802 		vk.createShadersEXT(device, (deUint32)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
803 		if (m_params.randomOrder && shaderCreateInfos.size() > 1)
804 		{
805 			std::swap(shaders[i], shaders[j]);
806 		}
807 		deUint32 n = 0;
808 		if (m_params.shaders.task == LINKED)
809 		{
810 			taskShader = shaders[n++];
811 		}
812 		if (m_params.shaders.mesh == LINKED)
813 		{
814 			meshShader = shaders[n++];
815 		}
816 		if (m_params.shaders.fragment == LINKED)
817 		{
818 			fragShader = shaders[n++];
819 		}
820 	}
821 
822 	const vk::VkCommandPoolCreateInfo	cmdPoolInfo =
823 	{
824 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType
825 		DE_NULL,												// pNext
826 		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags
827 		queueFamilyIndex,										// queuefamilyindex
828 	};
829 
830 	const vk::Move<vk::VkCommandPool>	cmdPool		(createCommandPool(vk, device, &cmdPoolInfo));
831 	const vk::Move<vk::VkCommandBuffer>	cmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
832 
833 	// Draw
834 	vk::beginCommandBuffer(vk, *cmdBuffer);
835 
836 	vk::VkImageMemoryBarrier preImageBarrier =
837 	{
838 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
839 		DE_NULL,										// const void*			pNext
840 		vk::VK_ACCESS_NONE,								// VkAccessFlags		srcAccessMask
841 		vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags		dstAccessMask
842 		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		oldLayout
843 		vk::VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
844 		VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
845 		VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
846 		**image,										// VkImage				image
847 		{
848 			vk::VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
849 			0u,											// uint32_t				baseMipLevel
850 			VK_REMAINING_MIP_LEVELS,					// uint32_t				mipLevels,
851 			0u,											// uint32_t				baseArray
852 			VK_REMAINING_ARRAY_LAYERS,					// uint32_t				arraySize
853 		}
854 	};
855 
856 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
857 
858 	const vk::VkClearValue				clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
859 	vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
860 	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true);
861 	vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1, &descriptorSet.get(), 0, DE_NULL);
862 
863 	bindNullRasterizationShaders(vk, *cmdBuffer, m_context.getDeviceFeatures());
864 	vk::VkShaderStageFlagBits stages[] = {
865 			vk::VK_SHADER_STAGE_TASK_BIT_EXT,
866 			vk::VK_SHADER_STAGE_MESH_BIT_EXT,
867 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
868 	};
869 	vk::VkShaderEXT shaders[] = {
870 		m_params.shaders.task != UNUSED ? taskShader : VK_NULL_HANDLE,
871 		m_params.shaders.mesh != UNUSED ? meshShader : VK_NULL_HANDLE,
872 		m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE,
873 	};
874 	vk.cmdBindShadersEXT(*cmdBuffer, 3, stages, shaders);
875 
876 	vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
877 
878 	vk::endRendering(vk, *cmdBuffer);
879 
880 	vk::VkImageMemoryBarrier postImageBarrier =
881 	{
882 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
883 		DE_NULL,										// const void*			pNext
884 		vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags		srcAccessMask
885 		vk::VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags		dstAccessMask
886 		vk::VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		oldLayout
887 		vk::VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
888 		VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
889 		VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
890 		**image,										// VkImage				image
891 		{
892 			vk::VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
893 			0u,											// uint32_t				baseMipLevel
894 			VK_REMAINING_MIP_LEVELS,					// uint32_t				mipLevels,
895 			0u,											// uint32_t				baseArray
896 			VK_REMAINING_ARRAY_LAYERS,					// uint32_t				arraySize
897 		}
898 	};
899 
900 	vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
901 
902 	const vk::VkBufferImageCopy	copyRegion =
903 	{
904 		0u,																		// VkDeviceSize				bufferOffset;
905 		0u,																		// deUint32					bufferRowLength;
906 		0u,																		// deUint32					bufferImageHeight;
907 		{
908 			vk::VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags		aspect;
909 			0u,																	// deUint32					mipLevel;
910 			0u,																	// deUint32					baseArrayLayer;
911 			1u,																	// deUint32					layerCount;
912 		},																		// VkImageSubresourceLayers	imageSubresource;
913 		{ 0, 0, 0 },															// VkOffset3D				imageOffset;
914 		{renderArea.extent.width, renderArea.extent.height, 1}					// VkExtent3D				imageExtent;
915 	};
916 	vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
917 
918 	vk::endCommandBuffer(vk, *cmdBuffer);
919 
920 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
921 
922 	// Cleanup
923 	if (m_params.shaders.task != UNUSED)
924 		vk.destroyShaderEXT(device, taskShader, DE_NULL);
925 
926 	if (m_params.shaders.mesh != UNUSED)
927 		vk.destroyShaderEXT(device, meshShader, DE_NULL);
928 
929 	if (m_params.shaders.fragment != UNUSED)
930 		vk.destroyShaderEXT(device, fragShader, DE_NULL);
931 
932 	if (m_params.shaders.fragment != UNUSED)
933 	{
934 		tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
935 
936 		const tcu::Vec4			white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
937 		const deInt32			width = resultBuffer.getWidth();
938 		const deInt32			height = resultBuffer.getHeight();
939 
940 		for (deInt32 j = 0; j < height; ++j)
941 		{
942 			for (deInt32 i = 0; i < width; ++i)
943 			{
944 				const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
945 				if (color != white)
946 				{
947 					log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")" << tcu::TestLog::EndMessage;
948 					return tcu::TestStatus::fail("Fail");
949 				}
950 			}
951 		}
952 	}
953 	if (m_params.shaders.mesh != UNUSED)
954 	{
955 		const vk::Allocation& outputBufferAllocation = outputBuffer.getAllocation();
956 		invalidateAlloc(vk, device, outputBufferAllocation);
957 
958 		const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
959 
960 		if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
961 		{
962 			log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 2, 3], but were[" << bufferPtr[0] << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", " << "]" << tcu::TestLog::EndMessage;
963 			return tcu::TestStatus::fail("Fail");
964 		}
965 	}
966 
967 	return tcu::TestStatus::pass("Pass");
968 }
969 
970 class MeshShaderObjectLinkCase : public vkt::TestCase
971 {
972 public:
MeshShaderObjectLinkCase(tcu::TestContext& testCtx, const std::string& name, const MeshParams& params)973 					MeshShaderObjectLinkCase	(tcu::TestContext& testCtx, const std::string& name, const MeshParams& params)
974 												: vkt::TestCase		(testCtx, name)
975 												, m_params			(params)
976 												{}
~MeshShaderObjectLinkCase(void)977 	virtual			~MeshShaderObjectLinkCase	(void) {}
978 
979 	void			checkSupport				(vkt::Context& context) const override;
980 	virtual void	initPrograms				(vk::SourceCollections& programCollection) const override;
981 	TestInstance*	createInstance				(Context& context) const override { return new MeshShaderObjectLinkInstance(context, m_params); }
982 private:
983 	MeshParams m_params;
984 };
985 
initPrograms(vk::SourceCollections& programCollection) const986 void MeshShaderObjectLinkCase::initPrograms (vk::SourceCollections& programCollection) const
987 {
988 	std::stringstream task;
989 	std::stringstream mesh;
990 	std::stringstream frag;
991 
992 	task
993 		<< "#version 450\n"
994 		<< "#extension GL_EXT_mesh_shader : enable\n"
995 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
996 		<< "void main ()\n"
997 		<< "{\n"
998 		<< "	EmitMeshTasksEXT(1u, 1u, 1u);\n"
999 		<< "}\n";
1000 
1001 	mesh
1002 		<< "#version 460\n"
1003 		<< "#extension GL_EXT_mesh_shader : require\n"
1004 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1005 		<< "layout(max_vertices = 3) out;\n"
1006 		<< "layout(max_primitives = 1) out;\n"
1007 		<< "layout(triangles) out;\n"
1008 		<< "layout(set = 0, binding = 0) buffer Output {\n"
1009 		<< "    uint values[4];\n"
1010 		<< "} buffer_out;\n\n"
1011 		<< "void main() {\n"
1012 		<< "      SetMeshOutputsEXT(3, 1);\n"
1013 		<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1014 		<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1015 		<< "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1016 		<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1017 		<< "      buffer_out.values[0] = 0u;\n"
1018 		<< "      buffer_out.values[1] = 1u;\n"
1019 		<< "      buffer_out.values[2] = 2u;\n"
1020 		<< "      buffer_out.values[3] = 3u;\n"
1021 		<< "}\n";
1022 
1023 	frag
1024 		<< "#version 450\n"
1025 		<< "layout (location=0) out vec4 outColor;\n"
1026 		<< "void main() {\n"
1027 		<< "    outColor = vec4(1.0f);\n"
1028 		<< "}\n";
1029 
1030 	programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1031 	programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1032 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1033 }
1034 
checkSupport(Context& context) const1035 void MeshShaderObjectLinkCase::checkSupport (Context& context) const
1036 {
1037 	context.requireDeviceFunctionality("VK_EXT_shader_object");
1038 
1039 	context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1040 	const auto& features = context.getMeshShaderFeaturesEXT();
1041 	if (!features.taskShader)
1042 		TCU_THROW(NotSupportedError, "Task shaders not supported");
1043 	if (!features.meshShader)
1044 		TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1045 }
1046 
typeToString(ShaderType type)1047 std::string typeToString(ShaderType type) {
1048 	if (type == UNUSED)
1049 		return "unused";
1050 
1051 	if (type == LINKED)
1052 		return "linked";
1053 
1054 	if (type == UNLINKED)
1055 		return "unlinked";
1056 
1057 	return {};
1058 }
1059 
1060 }
1061 
createShaderObjectLinkTests(tcu::TestContext& testCtx)1062 tcu::TestCaseGroup* createShaderObjectLinkTests (tcu::TestContext& testCtx)
1063 {
1064 	de::MovePtr<tcu::TestCaseGroup> linkGroup(new tcu::TestCaseGroup(testCtx, "link"));
1065 
1066 	const Shaders shaderTests[] =
1067 	{
1068 		{ LINKED, LINKED, UNLINKED, UNUSED, UNLINKED,		},
1069 		{ LINKED, LINKED, LINKED, UNUSED, UNLINKED,			},
1070 		{ LINKED, LINKED, LINKED, LINKED, UNLINKED,			},
1071 		{ LINKED, LINKED, LINKED, LINKED, LINKED,			},
1072 		{ LINKED, UNUSED, UNUSED, LINKED, UNLINKED,			},
1073 		{ LINKED, UNUSED, UNUSED, LINKED, LINKED,			},
1074 		{ LINKED, UNUSED, UNUSED, UNUSED, LINKED,			},
1075 		{ UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED	},
1076 		{ UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED		},
1077 		{ UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED		},
1078 		{ UNLINKED, LINKED, LINKED, UNUSED, UNLINKED		},
1079 		{ UNLINKED, LINKED, LINKED, LINKED, UNLINKED		},
1080 		{ UNLINKED, LINKED, LINKED, UNUSED, LINKED			},
1081 		{ UNLINKED, LINKED, LINKED, LINKED, LINKED			},
1082 		{ UNLINKED, UNUSED, UNUSED, LINKED, LINKED			},
1083 	};
1084 
1085 	const bool randomOrderTests[] =
1086 	{
1087 		false,
1088 		true,
1089 	};
1090 
1091 	const struct
1092 	{
1093 		BindType bindType;
1094 		const char* name;
1095 	} bindTypeTests[] =
1096 	{
1097 		{ SEPARATE,				"separate"				},
1098 		{ ONE_LINKED_UNLINKED,	"one_linked_unlinked"	},
1099 		{ ALL,					"all"					},
1100 	};
1101 
1102 	for (const auto& shaders : shaderTests)
1103 	{
1104 		std::string shadersName = "";
1105 		shadersName += typeToString(shaders.vertex) + "_";
1106 		shadersName += typeToString(shaders.tesellation_control) + "_";
1107 		shadersName += typeToString(shaders.tesellation_evaluation) + "_";
1108 		shadersName += typeToString(shaders.geometry) + "_";
1109 		shadersName += typeToString(shaders.fragment);
1110 		de::MovePtr<tcu::TestCaseGroup> shadersGroup(new tcu::TestCaseGroup(testCtx, shadersName.c_str()));
1111 
1112 		for (const auto& bindType : bindTypeTests)
1113 		{
1114 			de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, bindType.name));
1115 			for (const auto& randomOrder : randomOrderTests)
1116 			{
1117 				NextStages nextStages = {};
1118 				if (shaders.tesellation_control != UNUSED) {
1119 					nextStages.vertNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1120 					nextStages.tescNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1121 				}
1122 				if (shaders.geometry != UNUSED) {
1123 					nextStages.vertNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1124 					nextStages.teseNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1125 				}
1126 				if (shaders.fragment != UNUSED) {
1127 					nextStages.vertNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1128 					nextStages.teseNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1129 					nextStages.geomNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1130 				}
1131 
1132 				TestParams params = {
1133 					shaders,				// Shaders		shaders;
1134 					randomOrder,			// bool			randomOrder;
1135 					nextStages,				// NextStages	nextStages;
1136 					false,					// bool			separateLinked;
1137 					bindType.bindType,		// bool			separateBind;
1138 				};
1139 
1140 				std::string randomOrderName = randomOrder ? "random_order" : "default";
1141 
1142 				bindGroup->addChild(new ShaderObjectLinkCase(testCtx, randomOrderName, params));
1143 			}
1144 
1145 			if (shaders.vertex == LINKED || shaders.tesellation_control == LINKED || shaders.tesellation_evaluation == LINKED || shaders.geometry == LINKED || shaders.fragment == LINKED)
1146 			{
1147 				TestParams params = {
1148 					shaders,																												// Shaders		shaders;
1149 					false,																													// bool			randomOrder;
1150 					{
1151 						vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1152 						vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1153 						vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1154 						vk::VK_SHADER_STAGE_FRAGMENT_BIT, },																				// NextStages	nextStages;
1155 					true,																													// bool         separateLinked;
1156 					ALL,																													// BindType		separateBind
1157 				};
1158 
1159 				bindGroup->addChild(new ShaderObjectLinkCase(testCtx, "separate_link", params));
1160 			}
1161 			shadersGroup->addChild(bindGroup.release());
1162 		}
1163 		linkGroup->addChild(shadersGroup.release());
1164 	}
1165 
1166 	const struct
1167 	{
1168 		Shaders		shaders;
1169 		NextStages	nextStages;
1170 		const char*	name;
1171 	} nextStageTests[] =
1172 	{
1173 		{
1174 			{ UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED },
1175 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1176 			"vert_t"
1177 		},
1178 		{
1179 			{ UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED	},
1180 			{ vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1181 			"vert_g"
1182 		},
1183 		{
1184 			{ UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED	},
1185 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1186 			"vert_tg"
1187 		},
1188 		{
1189 			{ UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED	},
1190 			{ vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 0u, 0u, },
1191 			"vert_f"
1192 		},
1193 		{
1194 			{ UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED	},
1195 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1196 			"vert_tf"
1197 		},
1198 		{
1199 			{ UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED	},
1200 			{ vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1201 			"vert_gf"
1202 		},
1203 		{
1204 			{ UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED	},
1205 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1206 			"vert_tgf"
1207 		},
1208 		{
1209 			{ UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED	},
1210 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1211 			"tesc_t"
1212 		},
1213 		{
1214 			{ UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED	},
1215 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1216 			"tese_g"
1217 		},
1218 		{
1219 			{ UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED	},
1220 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, },
1221 			"tese_f"
1222 		},
1223 		{
1224 			{ UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED	},
1225 			{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1226 			"tese_gf"
1227 		},
1228 		{
1229 			{ UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED	},
1230 			{ vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0u, 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },
1231 			"geom_f"
1232 		},
1233 	};
1234 
1235 	de::MovePtr<tcu::TestCaseGroup> nextStageGroup(new tcu::TestCaseGroup(testCtx, "next_stage"));
1236 	for (const auto& nextStage : nextStageTests)
1237 	{
1238 		TestParams params = {
1239 			nextStage.shaders,
1240 			false,
1241 			nextStage.nextStages,
1242 			false,
1243 			ALL,
1244 		};
1245 		nextStageGroup->addChild(new ShaderObjectLinkCase(testCtx, nextStage.name, params));
1246 	}
1247 	linkGroup->addChild(nextStageGroup.release());
1248 
1249 	const MeshShaders meshShaderTests[] =
1250 	{
1251 		{ UNLINKED, UNLINKED, UNLINKED,		},
1252 		{ UNLINKED, UNLINKED, UNUSED,		},
1253 		{ LINKED, LINKED, UNLINKED,			},
1254 		{ UNLINKED, LINKED, LINKED,			},
1255 		{ LINKED, LINKED, LINKED,			},
1256 	};
1257 
1258 	for (const auto& meshShaders : meshShaderTests)
1259 	{
1260 		std::string name = "mesh_";
1261 		name += typeToString(meshShaders.task) + "_";
1262 		name += typeToString(meshShaders.mesh) + "_";
1263 		name += typeToString(meshShaders.fragment);
1264 		de::MovePtr<tcu::TestCaseGroup> meshGroup(new tcu::TestCaseGroup(testCtx, name.c_str()));
1265 
1266 		for (const auto& randomOrder : randomOrderTests)
1267 		{
1268 			MeshParams params = {
1269 				meshShaders,
1270 				randomOrder,
1271 				{ 0u, 0u, },
1272 			};
1273 
1274 			std::string randomOrderName = (randomOrder) ? "random_order" : "default";
1275 
1276 			meshGroup->addChild(new MeshShaderObjectLinkCase(testCtx, randomOrderName, params));
1277 		}
1278 		linkGroup->addChild(meshGroup.release());
1279 	}
1280 
1281 	const struct
1282 	{
1283 		MeshNextStages nextStages;
1284 		const char* name;
1285 	} meshNextStageTests[] =
1286 	{
1287 		{ { vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, },	"mesh"	},
1288 		{ { 0u, vk::VK_SHADER_STAGE_FRAGMENT_BIT, },	"frag"	},
1289 	};
1290 
1291 	de::MovePtr<tcu::TestCaseGroup> meshNextStageGroup(new tcu::TestCaseGroup(testCtx, "meshnext_stage"));
1292 	for (const auto& meshNextStage : meshNextStageTests)
1293 	{
1294 		MeshParams params = {
1295 			{ UNLINKED, UNLINKED, UNLINKED },
1296 			false,
1297 			meshNextStage.nextStages,
1298 		};
1299 		meshNextStageGroup->addChild(new MeshShaderObjectLinkCase(testCtx, meshNextStage.name, params));
1300 	}
1301 	linkGroup->addChild(meshNextStageGroup.release());
1302 
1303 	return linkGroup.release();
1304 }
1305 
1306 } // ShaderObject
1307 } // vkt
1308