1/*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Platform Synchronization tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSynchronizationSmokeTests.hpp"
25#include "vktSynchronizationUtil.hpp"
26
27#include "vktTestCaseUtil.hpp"
28#include "vktCustomInstancesDevices.hpp"
29
30#include "vkPlatform.hpp"
31#include "vkStrUtil.hpp"
32#include "vkRef.hpp"
33#include "vkRefUtil.hpp"
34#include "vkDeviceUtil.hpp"
35#include "vkSafetyCriticalUtil.hpp"
36
37#include "tcuTestLog.hpp"
38#include "tcuFormatUtil.hpp"
39#include "tcuCommandLine.hpp"
40
41#include "deUniquePtr.hpp"
42#include "deThread.hpp"
43#include "vkMemUtil.hpp"
44#include "vkQueryUtil.hpp"
45#include "vkPrograms.hpp"
46#include "vkTypeUtil.hpp"
47#include "vkCmdUtil.hpp"
48
49#include <limits>
50
51namespace vkt
52{
53namespace synchronization
54{
55
56using namespace vk;
57using namespace tcu;
58
59namespace
60{
61
62using std::vector;
63using std::string;
64using tcu::TestLog;
65using de::MovePtr;
66
67static const deUint64 DEFAULT_TIMEOUT = 2ull*1000*1000*1000; //!< 2 seconds in nanoseconds
68
69struct SemaphoreTestConfig
70{
71	SynchronizationType		synchronizationType;
72	VkSemaphoreType			semaphoreType;
73};
74
75void initShaders(SourceCollections& shaderCollection, SemaphoreTestConfig)
76{
77	shaderCollection.glslSources.add("glslvert") <<
78		glu::VertexSource(
79				"#version 310 es\n"
80				"precision mediump float;\n"
81				"layout (location = 0) in vec4 vertexPosition;\n"
82				"void main()\n"
83				"{\n"
84				"	gl_Position = vertexPosition;\n"
85				"}\n");
86
87	shaderCollection.glslSources.add("glslfrag") <<
88		glu::FragmentSource(
89				"#version 310 es\n"
90				"precision mediump float;\n"
91				"layout (location = 0) out vec4 outputColor;\n"
92				"void main()\n"
93				"{\n"
94				"	outputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
95				"}\n");
96}
97
98void buildShaders(SourceCollections& shaderCollection)
99{
100	initShaders(shaderCollection, { SynchronizationType::LEGACY, VK_SEMAPHORE_TYPE_BINARY });
101}
102
103Move<VkDevice> createTestDevice (Context& context, SemaphoreTestConfig& config, const VkInstance& instance, const InstanceInterface& vki, deUint32* outQueueFamilyIndex)
104{
105	const PlatformInterface&	vkp							= context.getPlatformInterface();
106	VkPhysicalDevice			physicalDevice				= chooseDevice(vki, instance, context.getTestContext().getCommandLine());
107	bool						validationEnabled			= context.getTestContext().getCommandLine().isValidationEnabled();
108	VkDeviceQueueCreateInfo		queueInfo;
109	VkDeviceCreateInfo			deviceInfo;
110	size_t						queueNdx;
111	const deUint32				queueCount					= 2u;
112	const float					queuePriority[queueCount]	= { 1.0f, 1.0f };
113
114	const vector<VkQueueFamilyProperties>			queueProps					= getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
115	const VkPhysicalDeviceFeatures					physicalDeviceFeatures		= getPhysicalDeviceFeatures(vki, physicalDevice);
116	VkPhysicalDeviceFeatures2						physicalDeviceFeatures2		{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, physicalDeviceFeatures };
117	VkPhysicalDeviceSynchronization2FeaturesKHR		synchronization2Features	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE };
118	VkPhysicalDeviceTimelineSemaphoreFeatures		timelineSemaphoreFeatures	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE };
119	void**											nextPtr						= &physicalDeviceFeatures2.pNext;
120
121	for (queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
122	{
123		if ((queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && (queueProps[queueNdx].queueCount >= queueCount))
124			break;
125	}
126
127	if (queueNdx >= queueProps.size())
128	{
129		// No queue family index found
130		std::ostringstream msg;
131		msg << "Cannot create device with " << queueCount << " graphics queues";
132
133		throw tcu::NotSupportedError(msg.str());
134	}
135
136	deMemset(&queueInfo,	0, sizeof(queueInfo));
137	deMemset(&deviceInfo,	0, sizeof(deviceInfo));
138
139	deMemset(&queueInfo, 0xcd, sizeof(queueInfo));
140	queueInfo.sType							= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
141	queueInfo.pNext							= DE_NULL;
142	queueInfo.flags							= (VkDeviceQueueCreateFlags)0u;
143	queueInfo.queueFamilyIndex				= (deUint32)queueNdx;
144	queueInfo.queueCount					= queueCount;
145	queueInfo.pQueuePriorities				= queuePriority;
146
147	vector<const char*> deviceExtensions;
148	bool useFeatures2 = false;
149	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
150	{
151		if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_timeline_semaphore"))
152			deviceExtensions.push_back("VK_KHR_timeline_semaphore");
153		addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
154		useFeatures2 = true;
155	}
156	if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
157	{
158		deviceExtensions.push_back("VK_KHR_synchronization2");
159		addToChainVulkanStructure(&nextPtr, synchronization2Features);
160		useFeatures2 = true;
161	}
162
163	void* pNext												= !useFeatures2 ? DE_NULL : &physicalDeviceFeatures2;
164#ifdef CTS_USES_VULKANSC
165	VkDeviceObjectReservationCreateInfo memReservationInfo	= context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
166	memReservationInfo.pNext								= pNext;
167	pNext													= &memReservationInfo;
168
169	VkPhysicalDeviceVulkanSC10Features sc10Features			= createDefaultSC10Features();
170	sc10Features.pNext										= pNext;
171	pNext													= &sc10Features;
172
173	VkPipelineCacheCreateInfo			pcCI;
174	std::vector<VkPipelinePoolSize>		poolSizes;
175	if (context.getTestContext().getCommandLine().isSubProcess())
176	{
177		if (context.getResourceInterface()->getCacheDataSize() > 0)
178		{
179			pcCI =
180			{
181				VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,		// VkStructureType				sType;
182				DE_NULL,											// const void*					pNext;
183				VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
184					VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
185				context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
186				context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
187			};
188			memReservationInfo.pipelineCacheCreateInfoCount		= 1;
189			memReservationInfo.pPipelineCacheCreateInfos		= &pcCI;
190		}
191
192		poolSizes							= context.getResourceInterface()->getPipelinePoolSizes();
193		if (!poolSizes.empty())
194		{
195			memReservationInfo.pipelinePoolSizeCount			= deUint32(poolSizes.size());
196			memReservationInfo.pPipelinePoolSizes				= poolSizes.data();
197		}
198	}
199#endif // CTS_USES_VULKANSC
200
201	deMemset(&deviceInfo, 0xcd, sizeof(deviceInfo));
202	deviceInfo.sType						= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
203	deviceInfo.pNext						= pNext;
204	deviceInfo.flags						= (VkDeviceCreateFlags)0u;
205	deviceInfo.queueCreateInfoCount			= 1u;
206	deviceInfo.pQueueCreateInfos			= &queueInfo;
207	deviceInfo.enabledExtensionCount		= static_cast<deUint32>(deviceExtensions.size());
208	deviceInfo.ppEnabledExtensionNames		= deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0];
209	deviceInfo.enabledLayerCount			= 0u;
210	deviceInfo.ppEnabledLayerNames			= DE_NULL;
211	deviceInfo.pEnabledFeatures				= !useFeatures2 ? &physicalDeviceFeatures : DE_NULL;
212
213	*outQueueFamilyIndex					= queueInfo.queueFamilyIndex;
214
215	return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceInfo);
216}
217
218struct BufferParameters
219{
220	const void*						memory;
221	VkDeviceSize					size;
222	VkBufferUsageFlags				usage;
223	VkSharingMode					sharingMode;
224	deUint32						queueFamilyCount;
225	const deUint32*					queueFamilyIndex;
226	VkAccessFlags					inputBarrierFlags;
227};
228
229struct Buffer
230{
231	MovePtr<Allocation>				allocation;
232	vector<VkMemoryBarrier>			memoryBarrier;
233	vk::Move<VkBuffer>				buffer;
234};
235
236void createVulkanBuffer (const DeviceInterface& vkd, VkDevice device, Allocator& allocator, const BufferParameters& bufferParameters, Buffer& buffer, MemoryRequirement visibility)
237{
238	VkBufferCreateInfo	bufferCreateParams;
239
240	deMemset(&bufferCreateParams, 0xcd, sizeof(bufferCreateParams));
241	bufferCreateParams.sType					= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
242	bufferCreateParams.pNext					= DE_NULL;
243	bufferCreateParams.flags					= 0;
244	bufferCreateParams.size						= bufferParameters.size;
245	bufferCreateParams.usage					= bufferParameters.usage;
246	bufferCreateParams.sharingMode				= bufferParameters.sharingMode;
247	bufferCreateParams.queueFamilyIndexCount	= bufferParameters.queueFamilyCount;
248	bufferCreateParams.pQueueFamilyIndices		= bufferParameters.queueFamilyIndex;
249
250	buffer.buffer		= createBuffer(vkd, device, &bufferCreateParams);
251	buffer.allocation	= allocator.allocate(getBufferMemoryRequirements(vkd, device, *buffer.buffer), visibility);
252
253	VK_CHECK(vkd.bindBufferMemory(device, *buffer.buffer, buffer.allocation->getMemory(), buffer.allocation->getOffset()));
254
255	// If caller provides a host memory buffer for the allocation, then go
256	// ahead and copy the provided data into the allocation and update the
257	// barrier list with the associated access
258	if (bufferParameters.memory != DE_NULL)
259	{
260		VkMemoryBarrier				barrier;
261
262		deMemcpy(buffer.allocation->getHostPtr(), bufferParameters.memory, (size_t)bufferParameters.size);
263		flushAlloc(vkd, device, *buffer.allocation);
264
265		deMemset(&barrier, 0xcd, sizeof(barrier));
266		barrier.sType			= VK_STRUCTURE_TYPE_MEMORY_BARRIER;
267		barrier.pNext			= DE_NULL;
268		barrier.srcAccessMask	= VK_ACCESS_HOST_WRITE_BIT;
269		barrier.dstAccessMask	= bufferParameters.inputBarrierFlags;
270
271		buffer.memoryBarrier.push_back(barrier);
272	}
273}
274
275struct ImageParameters
276{
277	VkImageType							imageType;
278	VkFormat							format;
279	VkExtent3D							extent3D;
280	deUint32							mipLevels;
281	VkSampleCountFlagBits				samples;
282	VkImageTiling						tiling;
283	VkBufferUsageFlags					usage;
284	VkSharingMode						sharingMode;
285	deUint32							queueFamilyCount;
286	const deUint32*						queueFamilyNdxList;
287	VkImageLayout						initialLayout;
288	VkImageLayout						finalLayout;
289	VkAccessFlags						barrierInputMask;
290};
291
292struct Image
293{
294	vk::Move<VkImage>					image;
295	vk::Move<VkImageView>				imageView;
296	MovePtr<Allocation>					allocation;
297	vector<VkImageMemoryBarrier>		imageMemoryBarrier;
298};
299
300void createVulkanImage (const DeviceInterface& vkd, VkDevice device, Allocator& allocator, const ImageParameters& imageParameters, Image& image, MemoryRequirement visibility)
301{
302	VkComponentMapping			componentMap;
303	VkImageSubresourceRange		subresourceRange;
304	VkImageViewCreateInfo		imageViewCreateInfo;
305	VkImageCreateInfo			imageCreateParams;
306	VkImageMemoryBarrier		imageBarrier;
307
308	deMemset(&imageCreateParams, 0xcd, sizeof(imageCreateParams));
309	imageCreateParams.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
310	imageCreateParams.pNext					= DE_NULL;
311	imageCreateParams.flags					= 0;
312	imageCreateParams.imageType				= imageParameters.imageType;
313	imageCreateParams.format				= imageParameters.format;
314	imageCreateParams.extent				= imageParameters.extent3D;
315	imageCreateParams.mipLevels				= imageParameters.mipLevels;
316	imageCreateParams.arrayLayers			= 1;
317	imageCreateParams.samples				= imageParameters.samples;
318	imageCreateParams.tiling				= imageParameters.tiling;
319	imageCreateParams.usage					= imageParameters.usage;
320	imageCreateParams.sharingMode			= imageParameters.sharingMode;
321	imageCreateParams.queueFamilyIndexCount	= imageParameters.queueFamilyCount;
322	imageCreateParams.pQueueFamilyIndices	= imageParameters.queueFamilyNdxList;
323	imageCreateParams.initialLayout			= imageParameters.initialLayout;
324
325	image.image			= createImage(vkd, device, &imageCreateParams);
326	image.allocation	= allocator.allocate(getImageMemoryRequirements(vkd, device, *image.image), visibility);
327
328	VK_CHECK(vkd.bindImageMemory(device, *image.image, image.allocation->getMemory(), image.allocation->getOffset()));
329
330	componentMap.r							= VK_COMPONENT_SWIZZLE_R;
331	componentMap.g							= VK_COMPONENT_SWIZZLE_G;
332	componentMap.b							= VK_COMPONENT_SWIZZLE_B;
333	componentMap.a							= VK_COMPONENT_SWIZZLE_A;
334
335	subresourceRange.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
336	subresourceRange.baseMipLevel			= 0;
337	subresourceRange.levelCount				= imageParameters.mipLevels;
338	subresourceRange.baseArrayLayer			= 0;
339	subresourceRange.layerCount				= 1;
340
341	deMemset(&imageViewCreateInfo, 0xcd, sizeof(imageViewCreateInfo));
342	imageViewCreateInfo.sType				= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
343	imageViewCreateInfo.pNext				= DE_NULL;
344	imageViewCreateInfo.flags				= 0;
345	imageViewCreateInfo.image				= image.image.get();
346	imageViewCreateInfo.viewType			= VK_IMAGE_VIEW_TYPE_2D;
347	imageViewCreateInfo.format				= imageParameters.format;
348	imageViewCreateInfo.components			= componentMap;
349	imageViewCreateInfo.subresourceRange	= subresourceRange;
350
351	image.imageView	= createImageView(vkd, device, &imageViewCreateInfo);
352
353	deMemset(&imageBarrier, 0xcd, sizeof(imageBarrier));
354	imageBarrier.sType					= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
355	imageBarrier.pNext					= DE_NULL;
356	imageBarrier.srcAccessMask			= 0;
357	imageBarrier.dstAccessMask			= imageParameters.barrierInputMask;
358	imageBarrier.oldLayout				= imageParameters.initialLayout;
359	imageBarrier.newLayout				= imageParameters.finalLayout;
360	imageBarrier.srcQueueFamilyIndex	= imageParameters.queueFamilyNdxList[0];
361	imageBarrier.dstQueueFamilyIndex	= imageParameters.queueFamilyNdxList[imageParameters.queueFamilyCount-1];
362	imageBarrier.image					= image.image.get();
363	imageBarrier.subresourceRange		= subresourceRange;
364
365	image.imageMemoryBarrier.push_back(imageBarrier);
366}
367
368struct RenderPassParameters
369{
370	VkFormat				colorFormat;
371	VkSampleCountFlagBits	colorSamples;
372};
373
374void  createColorOnlyRenderPass (const DeviceInterface& vkd, VkDevice device, const RenderPassParameters& renderPassParameters, vk::Move<VkRenderPass>& renderPass)
375{
376	VkAttachmentDescription				colorAttachmentDesc;
377	VkAttachmentReference				colorAttachmentRef;
378	VkAttachmentReference				stencilAttachmentRef;
379	VkSubpassDescription				subpassDesc;
380	VkRenderPassCreateInfo				renderPassParams;
381	VkRenderPass						newRenderPass;
382
383	colorAttachmentDesc.flags			= 0;
384	colorAttachmentDesc.format			= renderPassParameters.colorFormat;
385	colorAttachmentDesc.samples			= renderPassParameters.colorSamples;
386	colorAttachmentDesc.loadOp			= VK_ATTACHMENT_LOAD_OP_CLEAR;
387	colorAttachmentDesc.storeOp			= VK_ATTACHMENT_STORE_OP_STORE;
388	colorAttachmentDesc.stencilLoadOp	= VK_ATTACHMENT_LOAD_OP_DONT_CARE;
389	colorAttachmentDesc.stencilStoreOp	= VK_ATTACHMENT_STORE_OP_DONT_CARE;
390	colorAttachmentDesc.initialLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
391	colorAttachmentDesc.finalLayout		= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
392
393	colorAttachmentRef.attachment		= 0;
394	colorAttachmentRef.layout			= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
395
396	stencilAttachmentRef.attachment		= VK_ATTACHMENT_UNUSED;
397	stencilAttachmentRef.layout			= VK_IMAGE_LAYOUT_UNDEFINED;
398
399	subpassDesc.flags					= 0;
400	subpassDesc.pipelineBindPoint		= VK_PIPELINE_BIND_POINT_GRAPHICS;
401	subpassDesc.inputAttachmentCount	= 0;
402	subpassDesc.pInputAttachments		= DE_NULL;
403	subpassDesc.colorAttachmentCount	= 1;
404	subpassDesc.pColorAttachments		= &colorAttachmentRef;
405	subpassDesc.pResolveAttachments		= DE_NULL;
406	subpassDesc.pDepthStencilAttachment	= &stencilAttachmentRef;
407	subpassDesc.preserveAttachmentCount	= 0;
408	subpassDesc.pPreserveAttachments	= DE_NULL;
409
410	deMemset(&renderPassParams, 0xcd, sizeof(renderPassParams));
411	renderPassParams.sType				= VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
412	renderPassParams.pNext				= DE_NULL;
413	renderPassParams.flags				= 0;
414	renderPassParams.attachmentCount	= 1;
415	renderPassParams.pAttachments		= &colorAttachmentDesc;
416	renderPassParams.subpassCount		= 1;
417	renderPassParams.pSubpasses			= &subpassDesc;
418	renderPassParams.dependencyCount	= 0;
419	renderPassParams.pDependencies		= DE_NULL;
420
421	renderPass = createRenderPass(vkd, device, &renderPassParams);
422}
423
424struct ShaderDescParams
425{
426	VkShaderModule			shaderModule;
427	VkShaderStageFlagBits	stage;
428};
429
430struct VertexDesc
431{
432	deUint32	location;
433	VkFormat	format;
434	deUint32	stride;
435	deUint32	offset;
436};
437
438void createVertexInfo (const vector<VertexDesc>& vertexDesc, vector<VkVertexInputBindingDescription>& bindingList, vector<VkVertexInputAttributeDescription>& attrList, VkPipelineVertexInputStateCreateInfo& vertexInputState)
439{
440	for (vector<VertexDesc>::const_iterator vertDescIter = vertexDesc.begin(); vertDescIter != vertexDesc.end(); vertDescIter++)
441	{
442		deUint32							bindingId = 0;
443		VkVertexInputBindingDescription		bindingDesc;
444		VkVertexInputAttributeDescription	attrDesc;
445
446		bindingDesc.binding		= bindingId;
447		bindingDesc.stride		= vertDescIter->stride;
448		bindingDesc.inputRate	= VK_VERTEX_INPUT_RATE_VERTEX;
449		bindingList.push_back(bindingDesc);
450
451		attrDesc.location		= vertDescIter->location;
452		attrDesc.binding		= bindingId;
453		attrDesc.format			= vertDescIter->format;
454		attrDesc.offset			= vertDescIter->offset;
455		attrList.push_back(attrDesc);
456
457		bindingId++;
458	}
459
460	deMemset(&vertexInputState, 0xcd, sizeof(vertexInputState));
461	vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
462	vertexInputState.pNext = DE_NULL;
463	vertexInputState.flags = 0u;
464	vertexInputState.vertexBindingDescriptionCount = (deUint32)bindingList.size();
465	vertexInputState.pVertexBindingDescriptions = &bindingList[0];
466	vertexInputState.vertexAttributeDescriptionCount = (deUint32)attrList.size();
467	vertexInputState.pVertexAttributeDescriptions = &attrList[0];
468}
469
470void createCommandBuffer (const DeviceInterface& deviceInterface, const VkDevice device, const deUint32 queueFamilyNdx, vk::Move<VkCommandBuffer>* commandBufferRef, vk::Move<VkCommandPool>* commandPoolRef)
471{
472	vk::Move<VkCommandPool>		commandPool;
473	VkCommandBufferAllocateInfo	commandBufferInfo;
474	VkCommandBuffer				commandBuffer;
475
476	commandPool = createCommandPool(deviceInterface, device, 0u, queueFamilyNdx);
477
478	deMemset(&commandBufferInfo, 0xcd, sizeof(commandBufferInfo));
479	commandBufferInfo.sType					= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
480	commandBufferInfo.pNext					= DE_NULL;
481	commandBufferInfo.commandPool			= commandPool.get();
482	commandBufferInfo.level					= VK_COMMAND_BUFFER_LEVEL_PRIMARY;
483	commandBufferInfo.commandBufferCount	= 1;
484
485	VK_CHECK(deviceInterface.allocateCommandBuffers(device, &commandBufferInfo, &commandBuffer));
486	*commandBufferRef = vk::Move<VkCommandBuffer>(vk::check<VkCommandBuffer>(commandBuffer), Deleter<VkCommandBuffer>(deviceInterface, device, commandPool.get()));
487	*commandPoolRef = commandPool;
488}
489
490void createFences (const DeviceInterface& deviceInterface, VkDevice device, bool signaled, deUint32 numFences, VkFence* fence)
491{
492	VkFenceCreateInfo		fenceState;
493	VkFenceCreateFlags		signalFlag = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0;
494
495	deMemset(&fenceState, 0xcd, sizeof(fenceState));
496	fenceState.sType		= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
497	fenceState.pNext		= DE_NULL;
498	fenceState.flags		= signalFlag;
499
500	for (deUint32 ndx = 0; ndx < numFences; ndx++)
501		VK_CHECK(deviceInterface.createFence(device, &fenceState, DE_NULL, &fence[ndx]));
502}
503
504void destroyFences (const DeviceInterface& deviceInterface, VkDevice device, deUint32 numFences, VkFence* fence)
505{
506	for (deUint32 ndx = 0; ndx < numFences; ndx++)
507		deviceInterface.destroyFence(device, fence[ndx], DE_NULL);
508}
509
510struct RenderInfo
511{
512	deInt32							width;
513	deInt32							height;
514	deUint32						vertexBufferSize;
515	VkBuffer						vertexBuffer;
516	VkImage							image;
517	VkCommandBuffer					commandBuffer;
518	VkRenderPass					renderPass;
519	VkFramebuffer					framebuffer;
520	VkPipeline						pipeline;
521	deUint32						mipLevels;
522	const deUint32*					queueFamilyNdxList;
523	deUint32						queueFamilyNdxCount;
524	bool							waitEvent;
525	VkEvent							event;
526	vector<VkImageMemoryBarrier>*	barriers;
527};
528
529void  recordRenderPass (const DeviceInterface& deviceInterface, const RenderInfo& renderInfo)
530{
531	const VkDeviceSize					bindingOffset			= 0;
532	VkImageMemoryBarrier				renderBarrier;
533
534	if (renderInfo.waitEvent)
535		deviceInterface.cmdWaitEvents(renderInfo.commandBuffer, 1, &renderInfo.event, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
536
537	beginRenderPass(deviceInterface, renderInfo.commandBuffer, renderInfo.renderPass, renderInfo.framebuffer, makeRect2D(0, 0, renderInfo.width, renderInfo.height), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
538	deviceInterface.cmdBindPipeline(renderInfo.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, renderInfo.pipeline);
539	deviceInterface.cmdBindVertexBuffers(renderInfo.commandBuffer, 0u, 1u, &renderInfo.vertexBuffer, &bindingOffset);
540	deviceInterface.cmdDraw(renderInfo.commandBuffer, renderInfo.vertexBufferSize, 1, 0, 0);
541	endRenderPass(deviceInterface, renderInfo.commandBuffer);
542
543	deMemset(&renderBarrier, 0xcd, sizeof(renderBarrier));
544	renderBarrier.sType								= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
545	renderBarrier.pNext								= DE_NULL;
546	renderBarrier.srcAccessMask						= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
547	renderBarrier.dstAccessMask						= VK_ACCESS_TRANSFER_READ_BIT;
548	renderBarrier.oldLayout							= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
549	renderBarrier.newLayout							= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
550	renderBarrier.srcQueueFamilyIndex				= renderInfo.queueFamilyNdxList[0];
551	renderBarrier.dstQueueFamilyIndex				= renderInfo.queueFamilyNdxList[renderInfo.queueFamilyNdxCount-1];
552	renderBarrier.image								= renderInfo.image;
553	renderBarrier.subresourceRange.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
554	renderBarrier.subresourceRange.baseMipLevel		= 0;
555	renderBarrier.subresourceRange.levelCount		= renderInfo.mipLevels;
556	renderBarrier.subresourceRange.baseArrayLayer	= 0;
557	renderBarrier.subresourceRange.layerCount		= 1;
558	renderInfo.barriers->push_back(renderBarrier);
559}
560
561struct TransferInfo
562{
563	VkCommandBuffer					commandBuffer;
564	deUint32						width;
565	deUint32						height;
566	VkImage							image;
567	VkBuffer						buffer;
568	VkDeviceSize					size;
569	deUint32						mipLevel;
570	VkOffset3D						imageOffset;
571	vector<VkBufferMemoryBarrier>*	barriers;
572};
573
574void copyToCPU (const DeviceInterface& vkd, TransferInfo* transferInfo)
575{
576	VkBufferImageCopy	copyState;
577
578	copyState.bufferOffset						= 0;
579	copyState.bufferRowLength					= transferInfo->width;
580	copyState.bufferImageHeight					= transferInfo->height;
581	copyState.imageSubresource.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
582	copyState.imageSubresource.mipLevel			= transferInfo->mipLevel;
583	copyState.imageSubresource.baseArrayLayer	= 0;
584	copyState.imageSubresource.layerCount		= 1;
585	copyState.imageOffset						= transferInfo->imageOffset;
586	copyState.imageExtent.width					= (deInt32)(transferInfo->width);
587	copyState.imageExtent.height				= (deInt32)(transferInfo->height);
588	copyState.imageExtent.depth					= 1;
589
590	vkd.cmdCopyImageToBuffer(transferInfo->commandBuffer, transferInfo->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transferInfo->buffer, 1, &copyState);
591
592	{
593		VkBufferMemoryBarrier	bufferBarrier;
594		deMemset(&bufferBarrier, 0xcd, sizeof(bufferBarrier));
595		bufferBarrier.sType					= VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
596		bufferBarrier.pNext					= DE_NULL;
597		bufferBarrier.srcAccessMask			= VK_ACCESS_TRANSFER_WRITE_BIT;
598		bufferBarrier.dstAccessMask			= VK_ACCESS_HOST_READ_BIT;
599		bufferBarrier.srcQueueFamilyIndex	= VK_QUEUE_FAMILY_IGNORED;
600		bufferBarrier.dstQueueFamilyIndex	= VK_QUEUE_FAMILY_IGNORED;
601		bufferBarrier.buffer				= transferInfo->buffer;
602		bufferBarrier.offset				= 0;
603		bufferBarrier.size					= transferInfo->size;
604		transferInfo->barriers->push_back(bufferBarrier);
605	}
606}
607
608struct TestContext
609{
610	const DeviceInterface&		vkd;
611	const VkDevice				device;
612	const deUint32				queueFamilyIndex;
613	const BinaryCollection&		binaryCollection;
614	Allocator&					allocator;
615	de::SharedPtr<vk::ResourceInterface>	resourceInterface;
616
617	const tcu::Vec4*			vertices;
618	deUint32					numVertices;
619	tcu::IVec2					renderDimension;
620	VkFence						fences[2];
621	VkDeviceSize				renderSize;
622	MovePtr<Allocation>			renderReadBuffer;
623	MovePtr<Allocation>			vertexBufferAllocation;
624	vk::Move<VkBuffer>			vertexBuffer;
625	vk::Move<VkBuffer>			renderBuffer;
626	bool						waitEvent;
627	VkEvent						event;
628	vk::Move<VkImage>			image;
629	vk::Move<VkImageView>		imageView;
630	vk::Move<VkFramebuffer>		framebuffer;
631	vk::Move<VkCommandPool>		commandPool;
632	vk::Move<VkCommandBuffer>	cmdBuffer;
633	vk::Move<VkRenderPass>		renderPass;
634	vk::Move<VkPipelineCache>	pipelineCache;
635	vk::Move<VkPipeline>		pipeline;
636	MovePtr<Allocation>			imageAllocation;
637
638	TestContext (const DeviceInterface&					vkd_,
639				 const VkDevice							device_,
640				 deUint32								queueFamilyIndex_,
641				 const BinaryCollection&				binaryCollection_,
642				 Allocator&								allocator_,
643				 de::SharedPtr<vk::ResourceInterface>	resourceInterface_)
644		: vkd				(vkd_)
645		, device			(device_)
646		, queueFamilyIndex	(queueFamilyIndex_)
647		, binaryCollection	(binaryCollection_)
648		, allocator			(allocator_)
649		, resourceInterface	(resourceInterface_)
650		, vertices			(0)
651		, numVertices		(0)
652		, renderSize		(0)
653		, waitEvent			(false)
654	{
655		createFences(vkd, device, false, DE_LENGTH_OF_ARRAY(fences), fences);
656	}
657
658	~TestContext()
659	{
660		destroyFences(vkd, device, DE_LENGTH_OF_ARRAY(fences), fences);
661	}
662};
663
664void generateWork (TestContext& testContext)
665{
666	const DeviceInterface&						deviceInterface		= testContext.vkd;
667	const deUint32								queueFamilyNdx		= testContext.queueFamilyIndex;
668
669	// \note VkShaderModule is consumed by vkCreate*Pipelines() so it can be deleted
670	//       as pipeline has been constructed.
671	const vk::Unique<VkShaderModule>			vertShaderModule	(createShaderModule(deviceInterface,
672																						testContext.device,
673																						testContext.binaryCollection.get("glslvert"),
674																						(VkShaderModuleCreateFlags)0));
675
676	const vk::Unique<VkShaderModule>			fragShaderModule	(createShaderModule(deviceInterface,
677																						testContext.device,
678																						testContext.binaryCollection.get("glslfrag"),
679																						(VkShaderModuleCreateFlags)0));
680	const VkPipelineShaderStageCreateInfo		shaderStageParams[]	=
681	{
682		{
683			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
684			DE_NULL,
685			(VkPipelineShaderStageCreateFlags)0,
686			VK_SHADER_STAGE_VERTEX_BIT,
687			*vertShaderModule,
688			"main",
689			(const VkSpecializationInfo*)DE_NULL,
690		},
691		{
692			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
693			DE_NULL,
694			(VkPipelineShaderStageCreateFlags)0,
695			VK_SHADER_STAGE_FRAGMENT_BIT,
696			*fragShaderModule,
697			"main",
698			(const VkSpecializationInfo*)DE_NULL,
699		}
700	};
701
702	vk::Move<VkPipelineLayout>					layout;
703	vector<ShaderDescParams>					shaderDescParams;
704	VertexDesc									vertexDesc;
705	vector<VertexDesc>							vertexDescList;
706	vector<VkVertexInputAttributeDescription>	attrList;
707	vector<VkBufferMemoryBarrier>				bufferMemoryBarrier;
708	deUint32									memoryBarrierNdx;
709	deUint32									bufferMemoryBarrierNdx;
710	deUint32									imageMemoryBarrierNdx;
711	vector<VkVertexInputBindingDescription>		bindingList;
712	VkPipelineVertexInputStateCreateInfo		vertexInputState;
713	VkPipelineInputAssemblyStateCreateInfo		inputAssemblyState;
714	VkPipelineDepthStencilStateCreateInfo		depthStencilState;
715	VkPipelineColorBlendAttachmentState			blendAttachment;
716	VkPipelineColorBlendStateCreateInfo			blendState;
717	VkPipelineLayoutCreateInfo					pipelineLayoutState;
718	VkGraphicsPipelineCreateInfo				pipelineState;
719	VkPipelineCacheCreateInfo					cacheState;
720	VkViewport									viewport;
721	VkPipelineViewportStateCreateInfo			viewportInfo;
722	VkRect2D									scissor;
723	BufferParameters							bufferParameters;
724	Buffer										buffer;
725	RenderInfo									renderInfo;
726	ImageParameters								imageParameters;
727	Image										image;
728	VkPipelineRasterizationStateCreateInfo		rasterState;
729	VkPipelineMultisampleStateCreateInfo		multisampleState;
730	VkFramebufferCreateInfo						fbState;
731	VkCommandBufferBeginInfo					commandBufRecordState;
732	VkCommandBufferInheritanceInfo				inheritanceInfo;
733	RenderPassParameters						renderPassParameters;
734	TransferInfo								transferInfo;
735	vector<void*>								barrierList;
736	VkExtent3D									extent;
737	vector<VkMemoryBarrier>						memoryBarriers;
738	vector<VkBufferMemoryBarrier>				bufferBarriers;
739	vector<VkImageMemoryBarrier>				imageBarriers;
740
741	memoryBarrierNdx			= 0;
742	bufferMemoryBarrierNdx		= 0;
743	imageMemoryBarrierNdx		= 0;
744	buffer.memoryBarrier.resize(memoryBarrierNdx);
745	bufferMemoryBarrier.resize(bufferMemoryBarrierNdx);
746	image.imageMemoryBarrier.resize(imageMemoryBarrierNdx);
747
748	memoryBarriers.resize(0);
749	bufferBarriers.resize(0);
750	imageBarriers.resize(0);
751
752	bufferParameters.memory					= testContext.vertices;
753	bufferParameters.size					= testContext.numVertices * sizeof(tcu::Vec4);
754	bufferParameters.usage					= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
755	bufferParameters.sharingMode			= VK_SHARING_MODE_EXCLUSIVE;
756	bufferParameters.queueFamilyCount		= 1;
757	bufferParameters.queueFamilyIndex		= &queueFamilyNdx;
758	bufferParameters.inputBarrierFlags		= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
759	createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer, MemoryRequirement::HostVisible);
760	testContext.vertexBufferAllocation		= buffer.allocation;
761	testContext.vertexBuffer				= buffer.buffer;
762
763	bufferParameters.memory					= DE_NULL;
764	bufferParameters.size					= testContext.renderSize;
765	bufferParameters.usage					= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
766	bufferParameters.sharingMode			= VK_SHARING_MODE_EXCLUSIVE;
767	bufferParameters.queueFamilyCount		= 1;
768	bufferParameters.queueFamilyIndex		= &queueFamilyNdx;
769	bufferParameters.inputBarrierFlags		= 0;
770	createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer, MemoryRequirement::HostVisible);
771	testContext.renderReadBuffer			= buffer.allocation;
772	testContext.renderBuffer				= buffer.buffer;
773
774	extent.width							= testContext.renderDimension.x();
775	extent.height							= testContext.renderDimension.y();
776	extent.depth							= 1;
777
778	imageParameters.imageType				= VK_IMAGE_TYPE_2D;
779	imageParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
780	imageParameters.extent3D				= extent;
781	imageParameters.mipLevels				= 1;
782	imageParameters.samples					= VK_SAMPLE_COUNT_1_BIT;
783	imageParameters.tiling					= VK_IMAGE_TILING_OPTIMAL;
784	imageParameters.usage					= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
785	imageParameters.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
786	imageParameters.queueFamilyCount		= 1;
787	imageParameters.queueFamilyNdxList		= &queueFamilyNdx;
788	imageParameters.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
789	imageParameters.finalLayout				= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
790	imageParameters.barrierInputMask		= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
791	createVulkanImage(deviceInterface, testContext.device, testContext.allocator, imageParameters, image, MemoryRequirement::Any);
792	testContext.imageAllocation				= image.allocation;
793	testContext.image						= image.image;
794
795	for (size_t ndx = 0; ndx < image.imageMemoryBarrier.size(); ++ndx)
796		imageBarriers.push_back(image.imageMemoryBarrier[ndx]);
797
798	renderPassParameters.colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
799	renderPassParameters.colorSamples		= VK_SAMPLE_COUNT_1_BIT;
800	createColorOnlyRenderPass(deviceInterface, testContext.device, renderPassParameters, testContext.renderPass);
801
802	vertexDesc.location = 0;
803	vertexDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
804	vertexDesc.stride = sizeof(tcu::Vec4);
805	vertexDesc.offset = 0;
806	vertexDescList.push_back(vertexDesc);
807
808	createVertexInfo(vertexDescList, bindingList, attrList, vertexInputState);
809
810	deMemset(&inputAssemblyState, 0xcd, sizeof(inputAssemblyState));
811	inputAssemblyState.sType					= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
812	inputAssemblyState.pNext					= DE_NULL;
813	inputAssemblyState.flags					= 0u;
814	inputAssemblyState.topology					= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
815	inputAssemblyState.primitiveRestartEnable	= false;
816
817	viewport.x									= 0;
818	viewport.y									= 0;
819	viewport.width								= (float)testContext.renderDimension.x();
820	viewport.height								= (float)testContext.renderDimension.y();
821	viewport.minDepth							= 0;
822	viewport.maxDepth							= 1;
823
824	scissor.offset.x							= 0;
825	scissor.offset.y							= 0;
826	scissor.extent.width						= testContext.renderDimension.x();
827	scissor.extent.height						= testContext.renderDimension.y();
828
829	deMemset(&viewportInfo, 0xcd, sizeof(viewportInfo));
830	viewportInfo.sType							= VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
831	viewportInfo.pNext							= DE_NULL;
832	viewportInfo.flags							= 0;
833	viewportInfo.viewportCount					= 1;
834	viewportInfo.pViewports						= &viewport;
835	viewportInfo.scissorCount					= 1;
836	viewportInfo.pScissors						= &scissor;
837
838	deMemset(&rasterState, 0xcd, sizeof(rasterState));
839	rasterState.sType							= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
840	rasterState.pNext							= DE_NULL;
841	rasterState.flags							= 0;
842	rasterState.depthClampEnable				= VK_FALSE;
843	rasterState.rasterizerDiscardEnable			= VK_FALSE;
844	rasterState.polygonMode						= VK_POLYGON_MODE_FILL;
845	rasterState.cullMode						= VK_CULL_MODE_NONE;
846	rasterState.frontFace						= VK_FRONT_FACE_COUNTER_CLOCKWISE;
847	rasterState.depthBiasEnable					= VK_FALSE;
848	rasterState.lineWidth						= 1;
849
850	deMemset(&multisampleState, 0xcd, sizeof(multisampleState));
851	multisampleState.sType						= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
852	multisampleState.pNext						= DE_NULL;
853	multisampleState.flags						= 0;
854	multisampleState.rasterizationSamples		= VK_SAMPLE_COUNT_1_BIT;
855	multisampleState.sampleShadingEnable		= VK_FALSE;
856	multisampleState.pSampleMask				= DE_NULL;
857	multisampleState.alphaToCoverageEnable		= VK_FALSE;
858	multisampleState.alphaToOneEnable			= VK_FALSE;
859
860	deMemset(&depthStencilState, 0xcd, sizeof(depthStencilState));
861	depthStencilState.sType						= VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
862	depthStencilState.pNext						= DE_NULL;
863	depthStencilState.flags						= 0;
864	depthStencilState.depthTestEnable			= VK_FALSE;
865	depthStencilState.depthWriteEnable			= VK_FALSE;
866	depthStencilState.depthCompareOp			= VK_COMPARE_OP_ALWAYS;
867	depthStencilState.depthBoundsTestEnable		= VK_FALSE;
868	depthStencilState.stencilTestEnable			= VK_FALSE;
869	depthStencilState.front.failOp				= VK_STENCIL_OP_KEEP;
870	depthStencilState.front.passOp				= VK_STENCIL_OP_KEEP;
871	depthStencilState.front.depthFailOp			= VK_STENCIL_OP_KEEP;
872	depthStencilState.front.compareOp			= VK_COMPARE_OP_ALWAYS;
873	depthStencilState.front.compareMask			= 0u;
874	depthStencilState.front.writeMask			= 0u;
875	depthStencilState.front.reference			= 0u;
876	depthStencilState.back						= depthStencilState.front;
877
878	deMemset(&blendAttachment, 0xcd, sizeof(blendAttachment));
879	blendAttachment.blendEnable					= VK_FALSE;
880	blendAttachment.srcColorBlendFactor			= VK_BLEND_FACTOR_ZERO;
881	blendAttachment.srcAlphaBlendFactor			= VK_BLEND_FACTOR_ZERO;
882	blendAttachment.dstColorBlendFactor			= VK_BLEND_FACTOR_ZERO;
883	blendAttachment.dstAlphaBlendFactor			= VK_BLEND_FACTOR_ZERO;
884	blendAttachment.colorBlendOp				= VK_BLEND_OP_ADD;
885	blendAttachment.alphaBlendOp				= VK_BLEND_OP_ADD;
886	blendAttachment.colorWriteMask				= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
887
888	deMemset(&blendState, 0xcd, sizeof(blendState));
889	blendState.sType							= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
890	blendState.pNext							= DE_NULL;
891	blendState.flags							= 0;
892	blendState.logicOpEnable					= VK_FALSE;
893	blendState.logicOp							= VK_LOGIC_OP_COPY;
894	blendState.attachmentCount					= 1;
895	blendState.pAttachments						= &blendAttachment;
896
897	deMemset(&pipelineLayoutState, 0xcd, sizeof(pipelineLayoutState));
898	pipelineLayoutState.sType					= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
899	pipelineLayoutState.pNext					= DE_NULL;
900	pipelineLayoutState.flags					= 0;
901	pipelineLayoutState.setLayoutCount			= 0;
902	pipelineLayoutState.pSetLayouts				= DE_NULL;
903	pipelineLayoutState.pushConstantRangeCount	= 0;
904	pipelineLayoutState.pPushConstantRanges		= DE_NULL;
905	layout = createPipelineLayout(deviceInterface, testContext.device, &pipelineLayoutState, DE_NULL);
906
907	deMemset(&pipelineState, 0xcd, sizeof(pipelineState));
908	pipelineState.sType							= VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
909	pipelineState.pNext							= DE_NULL;
910	pipelineState.flags							= 0;
911	pipelineState.stageCount					= DE_LENGTH_OF_ARRAY(shaderStageParams);
912	pipelineState.pStages						= &shaderStageParams[0];
913	pipelineState.pVertexInputState				= &vertexInputState;
914	pipelineState.pInputAssemblyState			= &inputAssemblyState;
915	pipelineState.pTessellationState			= DE_NULL;
916	pipelineState.pViewportState				= &viewportInfo;
917	pipelineState.pRasterizationState			= &rasterState;
918	pipelineState.pMultisampleState				= &multisampleState;
919	pipelineState.pDepthStencilState			= &depthStencilState;
920	pipelineState.pColorBlendState				= &blendState;
921	pipelineState.pDynamicState					= (const VkPipelineDynamicStateCreateInfo*)DE_NULL;
922	pipelineState.layout						= layout.get();
923	pipelineState.renderPass					= testContext.renderPass.get();
924	pipelineState.subpass						= 0;
925	pipelineState.basePipelineHandle			= DE_NULL;
926	pipelineState.basePipelineIndex				= 0;
927
928	deMemset(&cacheState, 0xcd, sizeof(cacheState));
929	cacheState.sType							= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
930	cacheState.pNext							= DE_NULL;
931#ifndef CTS_USES_VULKANSC
932	cacheState.flags							= (VkPipelineCacheCreateFlags)0u;
933	cacheState.initialDataSize					= 0;
934	cacheState.pInitialData						= DE_NULL;
935#else
936	cacheState.flags							= VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT | VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT;
937	cacheState.initialDataSize					= testContext.resourceInterface->getCacheDataSize();
938	cacheState.pInitialData						= testContext.resourceInterface->getCacheData();
939#endif
940
941	testContext.pipelineCache					= createPipelineCache(deviceInterface, testContext.device, &cacheState);
942	testContext.pipeline						= createGraphicsPipeline(deviceInterface, testContext.device, testContext.pipelineCache.get(), &pipelineState);
943
944	deMemset(&fbState, 0xcd, sizeof(fbState));
945	fbState.sType								= VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
946	fbState.pNext								= DE_NULL;
947	fbState.flags								= 0;
948	fbState.renderPass							= testContext.renderPass.get();
949	fbState.attachmentCount						= 1;
950	fbState.pAttachments						= &image.imageView.get();
951	fbState.width								= (deUint32)testContext.renderDimension.x();
952	fbState.height								= (deUint32)testContext.renderDimension.y();
953	fbState.layers								= 1;
954
955	testContext.framebuffer	= createFramebuffer(deviceInterface, testContext.device, &fbState);
956	testContext.imageView	= image.imageView;
957
958	deMemset(&inheritanceInfo, 0xcd, sizeof(inheritanceInfo));
959	inheritanceInfo.sType						= VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
960	inheritanceInfo.pNext						= DE_NULL;
961	inheritanceInfo.renderPass					= testContext.renderPass.get();
962	inheritanceInfo.subpass						= 0;
963	inheritanceInfo.framebuffer					= *testContext.framebuffer;
964	inheritanceInfo.occlusionQueryEnable		= VK_FALSE;
965	inheritanceInfo.queryFlags					= 0u;
966	inheritanceInfo.pipelineStatistics			= 0u;
967
968	deMemset(&commandBufRecordState, 0xcd, sizeof(commandBufRecordState));
969	commandBufRecordState.sType					= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
970	commandBufRecordState.pNext					= DE_NULL;
971	commandBufRecordState.flags					= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
972	commandBufRecordState.pInheritanceInfo		= &inheritanceInfo;
973	VK_CHECK(deviceInterface.beginCommandBuffer(testContext.cmdBuffer.get(), &commandBufRecordState));
974
975	deviceInterface.cmdPipelineBarrier( testContext.cmdBuffer.get(),
976										VK_PIPELINE_STAGE_HOST_BIT,
977										VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
978										false,
979										(deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
980										(deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
981										(deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
982
983	memoryBarriers.resize(0);
984	bufferBarriers.resize(0);
985	imageBarriers.resize(0);
986
987	renderInfo.width				= testContext.renderDimension.x();
988	renderInfo.height				= testContext.renderDimension.y();
989	renderInfo.vertexBufferSize		= testContext.numVertices;
990	renderInfo.vertexBuffer			= testContext.vertexBuffer.get();
991	renderInfo.image				= testContext.image.get();
992	renderInfo.commandBuffer		= testContext.cmdBuffer.get();
993	renderInfo.renderPass			= testContext.renderPass.get();
994	renderInfo.framebuffer			= *testContext.framebuffer;
995	renderInfo.pipeline				= *testContext.pipeline;
996	renderInfo.mipLevels			= 1;
997	renderInfo.queueFamilyNdxList	= &queueFamilyNdx;
998	renderInfo.queueFamilyNdxCount	= 1;
999	renderInfo.waitEvent			= testContext.waitEvent;
1000	renderInfo.event				= testContext.event;
1001	renderInfo.barriers				= &imageBarriers;
1002	recordRenderPass(deviceInterface, renderInfo);
1003
1004	deviceInterface.cmdPipelineBarrier(	renderInfo.commandBuffer,
1005										VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1006										VK_PIPELINE_STAGE_TRANSFER_BIT,
1007										false,
1008										(deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
1009										(deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
1010										(deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
1011
1012	memoryBarriers.resize(0);
1013	bufferBarriers.resize(0);
1014	imageBarriers.resize(0);
1015
1016	transferInfo.commandBuffer		= renderInfo.commandBuffer;
1017	transferInfo.width				= testContext.renderDimension.x();
1018	transferInfo.height				= testContext.renderDimension.y();
1019	transferInfo.image				= renderInfo.image;
1020	transferInfo.buffer				= testContext.renderBuffer.get();
1021	transferInfo.size				= testContext.renderSize;
1022	transferInfo.mipLevel			= 0;
1023	transferInfo.imageOffset.x		= 0;
1024	transferInfo.imageOffset.y		= 0;
1025	transferInfo.imageOffset.z		= 0;
1026	transferInfo.barriers			= &bufferBarriers;
1027	copyToCPU(deviceInterface, &transferInfo);
1028
1029	deviceInterface.cmdPipelineBarrier(	transferInfo.commandBuffer,
1030										VK_PIPELINE_STAGE_TRANSFER_BIT,
1031										VK_PIPELINE_STAGE_HOST_BIT,
1032										false,
1033										(deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
1034										(deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
1035										(deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
1036
1037	memoryBarriers.resize(0);
1038	bufferBarriers.resize(0);
1039	imageBarriers.resize(0);
1040
1041	endCommandBuffer(deviceInterface, transferInfo.commandBuffer);
1042}
1043
1044tcu::TestStatus testFences (Context& context)
1045{
1046	TestLog&					log					= context.getTestContext().getLog();
1047	const DeviceInterface&		deviceInterface		= context.getDeviceInterface();
1048	const VkQueue				queue				= context.getUniversalQueue();
1049	const deUint32				queueFamilyIdx		= context.getUniversalQueueFamilyIndex();
1050	VkDevice					device				= context.getDevice();
1051	VkResult					waitStatus;
1052	VkResult					fenceStatus;
1053	TestContext					testContext			(deviceInterface, device, queueFamilyIdx, context.getBinaryCollection(), context.getDefaultAllocator(), context.getResourceInterface());
1054	void*						resultImage;
1055
1056	const tcu::Vec4				vertices[]			=
1057	{
1058		tcu::Vec4( 0.5f,  0.5f, 0.0f, 1.0f),
1059		tcu::Vec4(-0.5f,  0.5f, 0.0f, 1.0f),
1060		tcu::Vec4( 0.0f, -0.5f, 0.0f, 1.0f)
1061	};
1062
1063	testContext.vertices = vertices;
1064	testContext.numVertices = DE_LENGTH_OF_ARRAY(vertices);
1065	testContext.renderDimension = tcu::IVec2(256, 256);
1066	testContext.renderSize = sizeof(deUint32) * testContext.renderDimension.x() * testContext.renderDimension.y();
1067
1068	createCommandBuffer(deviceInterface, device, queueFamilyIdx, &testContext.cmdBuffer, &testContext.commandPool);
1069	generateWork(testContext);
1070
1071	// Default status is unsignaled
1072	fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1073	if (fenceStatus != VK_NOT_READY)
1074	{
1075		log << TestLog::Message << "testSynchronizationPrimitives fence 0 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1076		return tcu::TestStatus::fail("Fence in incorrect state");
1077	}
1078	fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[1]);
1079	if (fenceStatus != VK_NOT_READY)
1080	{
1081		log << TestLog::Message << "testSynchronizationPrimitives fence 1 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1082		return tcu::TestStatus::fail("Fence in incorrect state");
1083	}
1084
1085	VkSubmitInfo submitInfo { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 0u, DE_NULL, DE_NULL, 1u, &testContext.cmdBuffer.get(), 0, DE_NULL };
1086	VK_CHECK(deviceInterface.queueSubmit(queue, 1, &submitInfo, testContext.fences[0]));
1087
1088	// Wait with timeout = 0
1089	waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, 0u);
1090	if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1091	{
1092		// Will most likely end with VK_TIMEOUT
1093		log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1094		return tcu::TestStatus::fail("Failed to wait for a single fence");
1095	}
1096
1097	// Wait with a reasonable timeout
1098	waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, DEFAULT_TIMEOUT);
1099	if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1100	{
1101		// \note Wait can end with a timeout if DEFAULT_TIMEOUT is not sufficient
1102		log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1103		return tcu::TestStatus::fail("Failed to wait for a single fence");
1104	}
1105
1106	// Wait for work on fences[0] to actually complete
1107	waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, std::numeric_limits<deUint64>::max());
1108	if (waitStatus != VK_SUCCESS)
1109	{
1110		log << TestLog::Message << "testSynchPrimitives failed to wait for a fence" << TestLog::EndMessage;
1111		return tcu::TestStatus::fail("failed to wait for a fence");
1112	}
1113
1114	// Wait until timeout on a fence that has not been submitted
1115	waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[1], true, 1);
1116	if (waitStatus != VK_TIMEOUT)
1117	{
1118		log << TestLog::Message << "testSyncPrimitives failed to timeout on wait for single fence" << TestLog::EndMessage;
1119		return tcu::TestStatus::fail("failed to timeout on wait for single fence");
1120	}
1121
1122	// Check that the fence is signaled after the wait
1123	fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1124	if (fenceStatus != VK_SUCCESS)
1125	{
1126		log << TestLog::Message << "testSynchronizationPrimitives fence should be signaled but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1127		return tcu::TestStatus::fail("Fence in incorrect state");
1128	}
1129
1130	invalidateAlloc(deviceInterface, device, *testContext.renderReadBuffer);
1131	resultImage = testContext.renderReadBuffer->getHostPtr();
1132
1133	log << TestLog::Image(	"result",
1134							"result",
1135							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1136									tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1137									testContext.renderDimension.x(),
1138									testContext.renderDimension.y(),
1139									1,
1140									resultImage));
1141
1142	return TestStatus::pass("synchronization-fences passed");
1143}
1144
1145tcu::TestStatus testSemaphores (Context& context, SemaphoreTestConfig config)
1146{
1147	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
1148		TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
1149
1150	TestLog&					log					= context.getTestContext().getLog();
1151	const PlatformInterface&	platformInterface	= context.getPlatformInterface();
1152	const auto					instance			= context.getInstance();
1153	const auto&					instanceDriver		= context.getInstanceInterface();
1154	const VkPhysicalDevice		physicalDevice		= chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
1155	deUint32					queueFamilyIdx;
1156	bool						isTimelineSemaphore	(config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE);
1157	vk::Move<VkDevice>			device				(createTestDevice(context, config, instance, instanceDriver, &queueFamilyIdx));
1158
1159#ifndef CTS_USES_VULKANSC
1160	de::MovePtr<vk::DeviceDriver>	deviceInterfacePtr = de::MovePtr<DeviceDriver>(new DeviceDriver(platformInterface, instance, *device, context.getUsedApiVersion()));
1161#else
1162	de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>	deviceInterfacePtr = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(platformInterface, instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(), context.getUsedApiVersion()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
1163#endif // CTS_USES_VULKANSC
1164	const DeviceDriver&			deviceDriver		= *deviceInterfacePtr;
1165	SimpleAllocator				allocator			(deviceDriver,
1166													 *device,
1167													 getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice));
1168	const VkQueue				queue[2]			=
1169	{
1170		getDeviceQueue(deviceDriver, *device, queueFamilyIdx, 0),
1171		getDeviceQueue(deviceDriver, *device, queueFamilyIdx, 1)
1172	};
1173	VkResult							testStatus;
1174	TestContext							testContext1				(deviceDriver, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator, context.getResourceInterface());
1175	TestContext							testContext2				(deviceDriver, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator, context.getResourceInterface());
1176	Unique<VkSemaphore>					semaphore					(createSemaphoreType(deviceDriver, *device, config.semaphoreType));
1177	VkSemaphoreSubmitInfoKHR			waitSemaphoreSubmitInfo		= makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
1178	VkSemaphoreSubmitInfoKHR			signalSemaphoreSubmitInfo	= makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
1179
1180	const tcu::Vec4		vertices1[]			=
1181	{
1182		tcu::Vec4( 0.5f,  0.5f, 0.0f, 1.0f),
1183		tcu::Vec4(-0.5f,  0.5f, 0.0f, 1.0f),
1184		tcu::Vec4( 0.0f, -0.5f, 0.0f, 1.0f)
1185	};
1186
1187	const tcu::Vec4		vertices2[]			=
1188	{
1189		tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
1190		tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
1191		tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
1192	};
1193
1194	testContext1.vertices			= vertices1;
1195	testContext1.numVertices		= DE_LENGTH_OF_ARRAY(vertices1);
1196	testContext1.renderDimension	= tcu::IVec2(256, 256);
1197	testContext1.renderSize			= sizeof(deUint32) * testContext1.renderDimension.x() * testContext1.renderDimension.y();
1198
1199	testContext2.vertices			= vertices2;
1200	testContext2.numVertices		= DE_LENGTH_OF_ARRAY(vertices2);
1201	testContext2.renderDimension	= tcu::IVec2(256, 256);
1202	testContext2.renderSize			= sizeof(deUint32) * testContext2.renderDimension.x() * testContext2.renderDimension.y();
1203
1204	createCommandBuffer(deviceDriver, device.get(), queueFamilyIdx, &testContext1.cmdBuffer, &testContext1.commandPool);
1205	generateWork(testContext1);
1206
1207	createCommandBuffer(deviceDriver, device.get(), queueFamilyIdx, &testContext2.cmdBuffer, &testContext2.commandPool);
1208	generateWork(testContext2);
1209
1210	{
1211		VkCommandBufferSubmitInfoKHR	commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(testContext1.cmdBuffer.get());
1212		SynchronizationWrapperPtr		synchronizationWrapper = getSynchronizationWrapper(config.synchronizationType, deviceDriver, isTimelineSemaphore);
1213		synchronizationWrapper->addSubmitInfo(
1214			0u,										// deUint32								waitSemaphoreInfoCount
1215			DE_NULL,								// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
1216			1u,										// deUint32								commandBufferInfoCount
1217			&commandBufferSubmitInfo,				// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
1218			1u,										// deUint32								signalSemaphoreInfoCount
1219			&signalSemaphoreSubmitInfo,				// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
1220			DE_FALSE,
1221			isTimelineSemaphore
1222		);
1223
1224		VK_CHECK(synchronizationWrapper->queueSubmit(queue[0], testContext1.fences[0]));
1225	}
1226
1227	testStatus  = deviceDriver.waitForFences(device.get(), 1, &testContext1.fences[0], true, std::numeric_limits<deUint64>::max());
1228	if (testStatus != VK_SUCCESS)
1229	{
1230		log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1231		return tcu::TestStatus::fail("failed to wait for a set fence");
1232	}
1233
1234	invalidateAlloc(deviceDriver, device.get(), *testContext1.renderReadBuffer);
1235	void* resultImage = testContext1.renderReadBuffer->getHostPtr();
1236
1237	log << TestLog::Image(	"result",
1238							"result",
1239							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1240									tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1241									testContext1.renderDimension.x(),
1242									testContext1.renderDimension.y(),
1243									1,
1244									resultImage));
1245
1246	// The difference between the second submit info is that it will use a unique cmd buffer.
1247	// First submit signals a semaphore but not wait on a semaphore, the other waits on the
1248	// semaphore but not signal it.
1249	{
1250		VkCommandBufferSubmitInfoKHR	commandBufferSubmitInfo	= makeCommonCommandBufferSubmitInfo(testContext2.cmdBuffer.get());
1251		SynchronizationWrapperPtr		synchronizationWrapper	= getSynchronizationWrapper(config.synchronizationType, deviceDriver, isTimelineSemaphore);
1252		synchronizationWrapper->addSubmitInfo(
1253			1u,										// deUint32								waitSemaphoreInfoCount
1254			&waitSemaphoreSubmitInfo,				// const VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos
1255			1u,										// deUint32								commandBufferInfoCount
1256			&commandBufferSubmitInfo,				// const VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos
1257			0u,										// deUint32								signalSemaphoreInfoCount
1258			DE_NULL,								// const VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos
1259			isTimelineSemaphore
1260		);
1261
1262		VK_CHECK(synchronizationWrapper->queueSubmit(queue[1], testContext2.fences[0]));
1263	}
1264
1265	testStatus  = deviceDriver.waitForFences(device.get(), 1, &testContext2.fences[0], true, std::numeric_limits<deUint64>::max());
1266	if (testStatus != VK_SUCCESS)
1267	{
1268		log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1269		return tcu::TestStatus::fail("failed to wait for a set fence");
1270	}
1271
1272	invalidateAlloc(deviceDriver, device.get(), *testContext2.renderReadBuffer);
1273	resultImage = testContext2.renderReadBuffer->getHostPtr();
1274
1275	log << TestLog::Image(	"result",
1276							"result",
1277							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1278									tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1279									testContext2.renderDimension.x(),
1280									testContext2.renderDimension.y(),
1281									1,
1282									resultImage));
1283
1284	return tcu::TestStatus::pass("synchronization-semaphores passed");
1285}
1286
1287void checkSupport(Context& context, SemaphoreTestConfig config)
1288{
1289	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
1290		context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
1291	if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
1292		context.requireDeviceFunctionality("VK_KHR_synchronization2");
1293}
1294
1295} // anonymous
1296
1297tcu::TestCaseGroup* createSmokeTests (tcu::TestContext& textCtx)
1298{
1299	SynchronizationType					type		(SynchronizationType::LEGACY);
1300	de::MovePtr<tcu::TestCaseGroup>		smokeTests	(new tcu::TestCaseGroup(textCtx, "smoke"));
1301
1302	addFunctionCaseWithPrograms(smokeTests.get(), "fences", buildShaders, testFences);
1303	addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores",   checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_BINARY });
1304	addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_TIMELINE });
1305
1306	return smokeTests.release();
1307}
1308
1309tcu::TestCaseGroup* createSynchronization2SmokeTests(tcu::TestContext& textCtx)
1310{
1311	SynchronizationType					type		(SynchronizationType::SYNCHRONIZATION2);
1312	de::MovePtr<tcu::TestCaseGroup>		smokeTests	(new tcu::TestCaseGroup(textCtx, "smoke"));
1313
1314	addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores",   checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_BINARY });
1315	addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_TIMELINE });
1316
1317	return smokeTests.release();
1318}
1319
1320} // synchronization
1321} // vkt
1322