1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group 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 Synchronization tests utilities
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSynchronizationUtil.hpp"
25#include "vkTypeUtil.hpp"
26#include "vkCmdUtil.hpp"
27#include "vkBarrierUtil.hpp"
28#include "deStringUtil.hpp"
29#include <set>
30#include <limits>
31
32namespace vkt
33{
34namespace synchronization
35{
36using namespace vk;
37
38Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
39{
40	const VkCommandBufferAllocateInfo info =
41	{
42		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
43		DE_NULL,											// const void*			pNext;
44		commandPool,										// VkCommandPool		commandPool;
45		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
46		1u,													// deUint32				commandBufferCount;
47	};
48	return allocateCommandBuffer(vk, device, &info);
49}
50
51Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
52									  const VkDevice				device,
53									  const VkPipelineLayout		pipelineLayout,
54									  const VkShaderModule			shaderModule,
55									  const VkSpecializationInfo*	specInfo,
56									  PipelineCacheData&			pipelineCacheData,
57									  de::SharedPtr<vk::ResourceInterface> resourceInterface
58									  )
59{
60	const VkPipelineShaderStageCreateInfo shaderStageInfo =
61	{
62		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
63		DE_NULL,												// const void*						pNext;
64		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
65		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
66		shaderModule,											// VkShaderModule					module;
67		"main",													// const char*						pName;
68		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
69	};
70	const VkComputePipelineCreateInfo pipelineInfo =
71	{
72		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
73		DE_NULL,											// const void*						pNext;
74		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags			flags;
75		shaderStageInfo,									// VkPipelineShaderStageCreateInfo	stage;
76		pipelineLayout,										// VkPipelineLayout					layout;
77		DE_NULL,											// VkPipeline						basePipelineHandle;
78		0,													// deInt32							basePipelineIndex;
79	};
80
81	{
82		const vk::Unique<vk::VkPipelineCache>	pipelineCache	(pipelineCacheData.createPipelineCache(vk, device, resourceInterface));
83
84		vk::Move<vk::VkPipeline>				pipeline		(createComputePipeline(vk, device, *pipelineCache, &pipelineInfo));
85
86		// Refresh data from cache
87		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
88
89		return pipeline;
90	}
91}
92
93VkImageCreateInfo makeImageCreateInfo (const VkImageType			imageType,
94									   const VkExtent3D&			extent,
95									   const VkFormat				format,
96									   const VkImageUsageFlags		usage,
97									   const VkSampleCountFlagBits	samples,
98									   const VkImageTiling			tiling)
99{
100	return
101	{
102		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
103		DE_NULL,									// const void*              pNext;
104		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
105		imageType,									// VkImageType              imageType;
106		format,										// VkFormat                 format;
107		extent,										// VkExtent3D               extent;
108		1u,											// uint32_t                 mipLevels;
109		1u,											// uint32_t                 arrayLayers;
110		samples,									// VkSampleCountFlagBits    samples;
111		tiling,										// VkImageTiling            tiling;
112		usage,										// VkImageUsageFlags        usage;
113		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
114		0u,											// uint32_t                 queueFamilyIndexCount;
115		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
116		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
117	};
118}
119
120void beginRenderPassWithRasterizationDisabled (const DeviceInterface&	vk,
121											   const VkCommandBuffer	commandBuffer,
122											   const VkRenderPass		renderPass,
123											   const VkFramebuffer		framebuffer)
124{
125	const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
126
127	beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea);
128}
129
130GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
131															 const VkDevice					device,
132															 const VkShaderStageFlagBits	stage,
133															 const ProgramBinary&			binary,
134															 const VkSpecializationInfo*	specInfo)
135{
136	VkShaderModule module;
137	switch (stage)
138	{
139		case (VK_SHADER_STAGE_VERTEX_BIT):
140			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
141			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
142			module = *m_vertexShaderModule;
143			break;
144
145		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
146			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
147			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
148			module = *m_tessControlShaderModule;
149			break;
150
151		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
152			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
153			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
154			module = *m_tessEvaluationShaderModule;
155			break;
156
157		case (VK_SHADER_STAGE_GEOMETRY_BIT):
158			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
159			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
160			module = *m_geometryShaderModule;
161			break;
162
163		case (VK_SHADER_STAGE_FRAGMENT_BIT):
164			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
165			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
166			module = *m_fragmentShaderModule;
167			break;
168
169		default:
170			DE_FATAL("Invalid shader stage");
171			return *this;
172	}
173
174	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
175	{
176		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
177		DE_NULL,												// const void*							pNext;
178		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
179		stage,													// VkShaderStageFlagBits				stage;
180		module,													// VkShaderModule						module;
181		"main",													// const char*							pName;
182		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
183	};
184
185	m_shaderStageFlags |= stage;
186	m_shaderStages.push_back(pipelineShaderStageInfo);
187
188	return *this;
189}
190
191GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
192{
193	const VkVertexInputBindingDescription bindingDesc =
194	{
195		0u,									// uint32_t				binding;
196		stride,								// uint32_t				stride;
197		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
198	};
199	const VkVertexInputAttributeDescription attributeDesc =
200	{
201		0u,									// uint32_t			location;
202		0u,									// uint32_t			binding;
203		vertexFormat,						// VkFormat			format;
204		0u,									// uint32_t			offset;
205	};
206
207	m_vertexInputBindings.clear();
208	m_vertexInputBindings.push_back(bindingDesc);
209
210	m_vertexInputAttributes.clear();
211	m_vertexInputAttributes.push_back(attributeDesc);
212
213	return *this;
214}
215
216template<typename T>
217inline const T* dataPointer (const std::vector<T>& vec)
218{
219	return (vec.size() != 0 ? &vec[0] : DE_NULL);
220}
221
222Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
223												 const VkDevice			device,
224												 const VkPipelineLayout	pipelineLayout,
225												 const VkRenderPass		renderPass,
226												 PipelineCacheData&		pipelineCacheData,
227												 de::SharedPtr<vk::ResourceInterface> resourceInterface)
228{
229	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
230	{
231		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
232		DE_NULL,														// const void*                                 pNext;
233		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
234		static_cast<deUint32>(m_vertexInputBindings.size()),			// uint32_t                                    vertexBindingDescriptionCount;
235		dataPointer(m_vertexInputBindings),								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
236		static_cast<deUint32>(m_vertexInputAttributes.size()),			// uint32_t                                    vertexAttributeDescriptionCount;
237		dataPointer(m_vertexInputAttributes),							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
238	};
239
240	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
241																										 : m_primitiveTopology;
242	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
243	{
244		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
245		DE_NULL,														// const void*                                 pNext;
246		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
247		topology,														// VkPrimitiveTopology                         topology;
248		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
249	};
250
251	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
252	{
253		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
254		DE_NULL,														// const void*                                 pNext;
255		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
256		m_patchControlPoints,											// uint32_t                                    patchControlPoints;
257	};
258
259	const VkViewport	viewport	= makeViewport(m_renderSize);
260	const VkRect2D		scissor		= makeRect2D(m_renderSize);
261
262	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
263	{
264		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
265		DE_NULL,												// const void*                                 pNext;
266		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
267		1u,														// uint32_t                                    viewportCount;
268		&viewport,												// const VkViewport*                           pViewports;
269		1u,														// uint32_t                                    scissorCount;
270		&scissor,												// const VkRect2D*                             pScissors;
271	};
272
273	const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
274	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
275	{
276		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
277		DE_NULL,														// const void*                              pNext;
278		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
279		VK_FALSE,														// VkBool32                                 depthClampEnable;
280		isRasterizationDisabled,										// VkBool32                                 rasterizerDiscardEnable;
281		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
282		m_cullModeFlags,												// VkCullModeFlags							cullMode;
283		m_frontFace,													// VkFrontFace								frontFace;
284		VK_FALSE,														// VkBool32									depthBiasEnable;
285		0.0f,															// float									depthBiasConstantFactor;
286		0.0f,															// float									depthBiasClamp;
287		0.0f,															// float									depthBiasSlopeFactor;
288		1.0f,															// float									lineWidth;
289	};
290
291	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
292	{
293		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
294		DE_NULL,													// const void*								pNext;
295		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
296		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
297		VK_FALSE,													// VkBool32									sampleShadingEnable;
298		0.0f,														// float									minSampleShading;
299		DE_NULL,													// const VkSampleMask*						pSampleMask;
300		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
301		VK_FALSE													// VkBool32									alphaToOneEnable;
302	};
303
304	const VkStencilOpState stencilOpState = makeStencilOpState(
305		VK_STENCIL_OP_KEEP,		// stencil fail
306		VK_STENCIL_OP_KEEP,		// depth & stencil pass
307		VK_STENCIL_OP_KEEP,		// depth only fail
308		VK_COMPARE_OP_NEVER,	// compare op
309		0u,						// compare mask
310		0u,						// write mask
311		0u);					// reference
312
313	const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
314	{
315		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
316		DE_NULL,													// const void*								pNext;
317		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
318		VK_FALSE,													// VkBool32									depthTestEnable;
319		VK_FALSE,													// VkBool32									depthWriteEnable;
320		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
321		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
322		VK_FALSE,													// VkBool32									stencilTestEnable;
323		stencilOpState,												// VkStencilOpState							front;
324		stencilOpState,												// VkStencilOpState							back;
325		0.0f,														// float									minDepthBounds;
326		1.0f,														// float									maxDepthBounds;
327	};
328
329	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
330	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
331	{
332		m_blendEnable,						// VkBool32					blendEnable;
333		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
334		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
335		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
336		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
337		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
338		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
339		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
340	};
341
342	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
343	{
344		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
345		DE_NULL,													// const void*									pNext;
346		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
347		VK_FALSE,													// VkBool32										logicOpEnable;
348		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
349		1u,															// deUint32										attachmentCount;
350		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
351		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
352	};
353
354	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
355	{
356		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
357		DE_NULL,																// const void*										pNext;
358		(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
359		static_cast<deUint32>(m_shaderStages.size()),							// deUint32											stageCount;
360		&m_shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
361		&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
362		&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
363		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
364		(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),		// const VkPipelineViewportStateCreateInfo*			pViewportState;
365		&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
366		(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),	// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
367		(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),	// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
368		(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),		// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
369		DE_NULL,																// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
370		pipelineLayout,															// VkPipelineLayout									layout;
371		renderPass,																// VkRenderPass										renderPass;
372		0u,																		// deUint32											subpass;
373		DE_NULL,																// VkPipeline										basePipelineHandle;
374		0,																		// deInt32											basePipelineIndex;
375	};
376
377	{
378		const vk::Unique<vk::VkPipelineCache>	pipelineCache(pipelineCacheData.createPipelineCache(vk, device, resourceInterface));
379		vk::Move<vk::VkPipeline>				pipeline		(createGraphicsPipeline(vk, device, *pipelineCache, &graphicsPipelineInfo));
380
381		// Refresh data from cache
382		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
383
384		return pipeline;
385	}
386}
387
388// Uses some structures added by VK_KHR_synchronization2 to fill legacy structures.
389// With this approach we dont have to create branch in each test (one for legacy
390// second for new synchronization), this helps to reduce code of some tests.
391class LegacySynchronizationWrapper : public SynchronizationWrapperBase
392{
393protected:
394
395	struct SubmitInfoData
396	{
397		deUint32		waitSemaphoreCount;
398		std::size_t		waitSemaphoreIndex;
399		std::size_t		waitSemaphoreValueIndexPlusOne;
400		deUint32		commandBufferCount;
401		deUint32		commandBufferIndex;
402		deUint32		signalSemaphoreCount;
403		std::size_t		signalSemaphoreIndex;
404		std::size_t		signalSemaphoreValueIndexPlusOne;
405	};
406
407	bool isStageFlagAllowed(VkPipelineStageFlags2 stage) const
408	{
409		// synchronization2 suports more stages then legacy synchronization
410		// and so SynchronizationWrapper can only be used for cases that
411		// operate on stages also supported by legacy synchronization
412		// NOTE: if some tests hits assertion that uses this method then this
413		// test should not use synchronizationWrapper - it should be synchronization2 exclusive
414
415		static const std::set<deUint32> allowedStages
416		{
417			VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
418			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
419			VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
420			VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
421			VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
422			VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT,
423			VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
424			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
425			VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
426			VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
427			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
428			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
429			VK_PIPELINE_STAGE_TRANSFER_BIT,
430			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
431			VK_PIPELINE_STAGE_HOST_BIT,
432			VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
433			VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
434#ifndef CTS_USES_VULKANSC
435			VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
436			VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
437			VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
438			VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
439#endif // CTS_USES_VULKANSC
440			VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
441#ifndef CTS_USES_VULKANSC
442			VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV,
443			VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV,
444			VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT,
445			VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV,
446#endif // CTS_USES_VULKANSC
447			VK_PIPELINE_STAGE_NONE_KHR,
448		};
449
450		if (stage > static_cast<deUint64>(std::numeric_limits<deUint32>::max()))
451			return false;
452
453		return (allowedStages.find(static_cast<deUint32>(stage)) != allowedStages.end());
454	}
455
456	bool isAccessFlagAllowed(VkAccessFlags2 access) const
457	{
458		// synchronization2 suports more access flags then legacy synchronization
459		// and so SynchronizationWrapper can only be used for cases that
460		// operate on access flags also supported by legacy synchronization
461		// NOTE: if some tests hits assertion that uses this method then this
462		// test should not use synchronizationWrapper - it should be synchronization2 exclusive
463
464		static const std::set<deUint32> allowedAccessFlags
465		{
466			VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
467			VK_ACCESS_INDEX_READ_BIT,
468			VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
469			VK_ACCESS_UNIFORM_READ_BIT,
470			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
471			VK_ACCESS_SHADER_READ_BIT,
472			VK_ACCESS_SHADER_WRITE_BIT,
473			VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
474			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
475			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
476			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
477			VK_ACCESS_TRANSFER_READ_BIT,
478			VK_ACCESS_TRANSFER_WRITE_BIT,
479			VK_ACCESS_HOST_READ_BIT,
480			VK_ACCESS_HOST_WRITE_BIT,
481			VK_ACCESS_MEMORY_READ_BIT,
482			VK_ACCESS_MEMORY_WRITE_BIT,
483#ifndef CTS_USES_VULKANSC
484			VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
485			VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
486			VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
487			VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
488#endif // CTS_USES_VULKANSC
489			VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT,
490#ifndef CTS_USES_VULKANSC
491			VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
492			VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
493#endif // CTS_USES_VULKANSC
494			VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR ,
495#ifndef CTS_USES_VULKANSC
496			VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,
497			VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV,
498			VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV,
499#endif // CTS_USES_VULKANSC
500			VK_ACCESS_NONE_KHR,
501		};
502
503		if (access > static_cast<deUint64>(std::numeric_limits<deUint32>::max()))
504			return false;
505
506		return (allowedAccessFlags.find(static_cast<deUint32>(access)) != allowedAccessFlags.end());
507	}
508
509public:
510	LegacySynchronizationWrapper(const DeviceInterface& vk, bool usingTimelineSemaphores, deUint32 submitInfoCount = 1u)
511		: SynchronizationWrapperBase	(vk)
512		, m_submited					(DE_FALSE)
513	{
514		m_waitSemaphores.reserve(submitInfoCount);
515		m_signalSemaphores.reserve(submitInfoCount);
516		m_waitDstStageMasks.reserve(submitInfoCount);
517		m_commandBuffers.reserve(submitInfoCount);
518		m_submitInfoData.reserve(submitInfoCount);
519
520		if (usingTimelineSemaphores)
521			m_timelineSemaphoreValues.reserve(2 * submitInfoCount);
522	}
523
524	~LegacySynchronizationWrapper() = default;
525
526	void addSubmitInfo(deUint32								waitSemaphoreInfoCount,
527					   const VkSemaphoreSubmitInfo*			pWaitSemaphoreInfos,
528					   deUint32								commandBufferInfoCount,
529					   const VkCommandBufferSubmitInfo*		pCommandBufferInfos,
530					   deUint32								signalSemaphoreInfoCount,
531					   const VkSemaphoreSubmitInfo*			pSignalSemaphoreInfos,
532					   bool									usingWaitTimelineSemaphore,
533					   bool									usingSignalTimelineSemaphore) override
534	{
535		m_submitInfoData.push_back(SubmitInfoData{ waitSemaphoreInfoCount, 0, 0, commandBufferInfoCount, 0u, signalSemaphoreInfoCount, 0, 0 });
536		SubmitInfoData& si = m_submitInfoData.back();
537
538		// memorize wait values
539		if (usingWaitTimelineSemaphore)
540		{
541			DE_ASSERT(pWaitSemaphoreInfos);
542			si.waitSemaphoreValueIndexPlusOne = m_timelineSemaphoreValues.size() + 1;
543			for (deUint32 i = 0; i < waitSemaphoreInfoCount; ++i)
544				m_timelineSemaphoreValues.push_back(pWaitSemaphoreInfos[i].value);
545		}
546
547		// memorize signal values
548		if (usingSignalTimelineSemaphore)
549		{
550			DE_ASSERT(pSignalSemaphoreInfos);
551			si.signalSemaphoreValueIndexPlusOne = m_timelineSemaphoreValues.size() + 1;
552			for (deUint32 i = 0; i < signalSemaphoreInfoCount; ++i)
553				m_timelineSemaphoreValues.push_back(pSignalSemaphoreInfos[i].value);
554		}
555
556		// construct list of semaphores that we need to wait on
557		if (waitSemaphoreInfoCount)
558		{
559			si.waitSemaphoreIndex = m_waitSemaphores.size();
560			for (deUint32 i = 0; i < waitSemaphoreInfoCount; ++i)
561			{
562				DE_ASSERT(isStageFlagAllowed(pWaitSemaphoreInfos[i].stageMask));
563				m_waitSemaphores.push_back(pWaitSemaphoreInfos[i].semaphore);
564				m_waitDstStageMasks.push_back(static_cast<VkPipelineStageFlags>(pWaitSemaphoreInfos[i].stageMask));
565			}
566		}
567
568		// construct list of command buffers
569		if (commandBufferInfoCount)
570		{
571			si.commandBufferIndex = static_cast<deUint32>(m_commandBuffers.size());
572			for (deUint32 i = 0; i < commandBufferInfoCount; ++i)
573				m_commandBuffers.push_back(pCommandBufferInfos[i].commandBuffer);
574		}
575
576		// construct list of semaphores that will be signaled
577		if (signalSemaphoreInfoCount)
578		{
579			si.signalSemaphoreIndex = m_signalSemaphores.size();
580			for (deUint32 i = 0; i < signalSemaphoreInfoCount; ++i)
581				m_signalSemaphores.push_back(pSignalSemaphoreInfos[i].semaphore);
582		}
583	}
584
585	void cmdPipelineBarrier(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo) const override
586	{
587		DE_ASSERT(pDependencyInfo);
588
589#ifndef CTS_USES_VULKANSC
590		VkPipelineStageFlags	srcStageMask				= VK_PIPELINE_STAGE_NONE;
591		VkPipelineStageFlags	dstStageMask				= VK_PIPELINE_STAGE_NONE;
592#else
593		VkPipelineStageFlags	srcStageMask				= VK_PIPELINE_STAGE_NONE_KHR;
594		VkPipelineStageFlags	dstStageMask				= VK_PIPELINE_STAGE_NONE_KHR;
595#endif // CTS_USES_VULKANSC
596		deUint32				memoryBarrierCount			= pDependencyInfo->memoryBarrierCount;
597		VkMemoryBarrier*		pMemoryBarriers				= DE_NULL;
598		deUint32				bufferMemoryBarrierCount	= pDependencyInfo->bufferMemoryBarrierCount;
599		VkBufferMemoryBarrier*	pBufferMemoryBarriers		= DE_NULL;
600		deUint32				imageMemoryBarrierCount		= pDependencyInfo->imageMemoryBarrierCount;
601		VkImageMemoryBarrier*	pImageMemoryBarriers		= DE_NULL;
602
603		// translate VkMemoryBarrier2 to VkMemoryBarrier
604		std::vector<VkMemoryBarrier> memoryBarriers;
605		if (memoryBarrierCount)
606		{
607			memoryBarriers.reserve(memoryBarrierCount);
608			for (deUint32 i = 0; i < memoryBarrierCount; ++i)
609			{
610				const VkMemoryBarrier2& pMemoryBarrier = pDependencyInfo->pMemoryBarriers[i];
611
612				DE_ASSERT(isStageFlagAllowed(pMemoryBarrier.srcStageMask));
613				DE_ASSERT(isStageFlagAllowed(pMemoryBarrier.dstStageMask));
614				DE_ASSERT(isAccessFlagAllowed(pMemoryBarrier.srcAccessMask));
615				DE_ASSERT(isAccessFlagAllowed(pMemoryBarrier.dstAccessMask));
616
617				srcStageMask |= static_cast<VkPipelineStageFlags>(pMemoryBarrier.srcStageMask);
618				dstStageMask |= static_cast<VkPipelineStageFlags>(pMemoryBarrier.dstStageMask);
619				memoryBarriers.push_back(makeMemoryBarrier(
620					static_cast<VkAccessFlags>(pMemoryBarrier.srcAccessMask),
621					static_cast<VkAccessFlags>(pMemoryBarrier.dstAccessMask)
622				));
623			}
624			pMemoryBarriers = &memoryBarriers[0];
625		}
626
627		// translate VkBufferMemoryBarrier2 to VkBufferMemoryBarrier
628		std::vector<VkBufferMemoryBarrier> bufferMemoryBarriers;
629		if (bufferMemoryBarrierCount)
630		{
631			bufferMemoryBarriers.reserve(bufferMemoryBarrierCount);
632			for (deUint32 i = 0; i < bufferMemoryBarrierCount; ++i)
633			{
634				const VkBufferMemoryBarrier2& pBufferMemoryBarrier = pDependencyInfo->pBufferMemoryBarriers[i];
635
636				DE_ASSERT(isStageFlagAllowed(pBufferMemoryBarrier.srcStageMask));
637				DE_ASSERT(isStageFlagAllowed(pBufferMemoryBarrier.dstStageMask));
638				DE_ASSERT(isAccessFlagAllowed(pBufferMemoryBarrier.srcAccessMask));
639				DE_ASSERT(isAccessFlagAllowed(pBufferMemoryBarrier.dstAccessMask));
640
641				srcStageMask |= static_cast<VkPipelineStageFlags>(pBufferMemoryBarrier.srcStageMask);
642				dstStageMask |= static_cast<VkPipelineStageFlags>(pBufferMemoryBarrier.dstStageMask);
643				bufferMemoryBarriers.push_back(makeBufferMemoryBarrier(
644					static_cast<VkAccessFlags>(pBufferMemoryBarrier.srcAccessMask),
645					static_cast<VkAccessFlags>(pBufferMemoryBarrier.dstAccessMask),
646					pBufferMemoryBarrier.buffer,
647					pBufferMemoryBarrier.offset,
648					pBufferMemoryBarrier.size,
649					pBufferMemoryBarrier.srcQueueFamilyIndex,
650					pBufferMemoryBarrier.dstQueueFamilyIndex
651				));
652			}
653			pBufferMemoryBarriers = &bufferMemoryBarriers[0];
654		}
655
656		// translate VkImageMemoryBarrier2 to VkImageMemoryBarrier
657		std::vector<VkImageMemoryBarrier> imageMemoryBarriers;
658		if (imageMemoryBarrierCount)
659		{
660			imageMemoryBarriers.reserve(imageMemoryBarrierCount);
661			for (deUint32 i = 0; i < imageMemoryBarrierCount; ++i)
662			{
663				const VkImageMemoryBarrier2& pImageMemoryBarrier = pDependencyInfo->pImageMemoryBarriers[i];
664
665				DE_ASSERT(isStageFlagAllowed(pImageMemoryBarrier.srcStageMask));
666				DE_ASSERT(isStageFlagAllowed(pImageMemoryBarrier.dstStageMask));
667				DE_ASSERT(isAccessFlagAllowed(pImageMemoryBarrier.srcAccessMask));
668				DE_ASSERT(isAccessFlagAllowed(pImageMemoryBarrier.dstAccessMask));
669
670				srcStageMask |= static_cast<VkPipelineStageFlags>(pImageMemoryBarrier.srcStageMask);
671				dstStageMask |= static_cast<VkPipelineStageFlags>(pImageMemoryBarrier.dstStageMask);
672				imageMemoryBarriers.push_back(makeImageMemoryBarrier(
673					static_cast<VkAccessFlags>(pImageMemoryBarrier.srcAccessMask),
674					static_cast<VkAccessFlags>(pImageMemoryBarrier.dstAccessMask),
675					pImageMemoryBarrier.oldLayout,
676					pImageMemoryBarrier.newLayout,
677					pImageMemoryBarrier.image,
678					pImageMemoryBarrier.subresourceRange,
679					pImageMemoryBarrier.srcQueueFamilyIndex,
680					pImageMemoryBarrier.dstQueueFamilyIndex
681				));
682			}
683			pImageMemoryBarriers = &imageMemoryBarriers[0];
684		}
685
686		m_vk.cmdPipelineBarrier(
687			commandBuffer,
688			srcStageMask,
689			dstStageMask,
690			(VkDependencyFlags)0,
691			memoryBarrierCount,
692			pMemoryBarriers,
693			bufferMemoryBarrierCount,
694			pBufferMemoryBarriers,
695			imageMemoryBarrierCount,
696			pImageMemoryBarriers
697		);
698	}
699
700	void cmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo) const override
701	{
702		DE_ASSERT(pDependencyInfo);
703
704#ifndef CTS_USES_VULKANSC
705		VkPipelineStageFlags2 srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
706#else
707		VkPipelineStageFlags2 srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
708#endif // CTS_USES_VULKANSC
709		if (pDependencyInfo->pMemoryBarriers)
710			srcStageMask = pDependencyInfo->pMemoryBarriers[0].srcStageMask;
711		if (pDependencyInfo->pBufferMemoryBarriers)
712			srcStageMask = pDependencyInfo->pBufferMemoryBarriers[0].srcStageMask;
713		if (pDependencyInfo->pImageMemoryBarriers)
714			srcStageMask = pDependencyInfo->pImageMemoryBarriers[0].srcStageMask;
715
716		DE_ASSERT(isStageFlagAllowed(srcStageMask));
717		m_vk.cmdSetEvent(commandBuffer, event, static_cast<VkPipelineStageFlags>(srcStageMask));
718	}
719
720	void cmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 flag) const override
721	{
722		DE_ASSERT(isStageFlagAllowed(flag));
723		VkPipelineStageFlags legacyStageMask = static_cast<VkPipelineStageFlags>(flag);
724		m_vk.cmdResetEvent(commandBuffer, event, legacyStageMask);
725	}
726
727	void cmdWaitEvents(VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfo) const override
728	{
729		DE_ASSERT(pDependencyInfo);
730
731#ifndef CTS_USES_VULKANSC
732		VkPipelineStageFlags2				srcStageMask				= VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
733		VkPipelineStageFlags2				dstStageMask				= VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
734#else
735		VkPipelineStageFlags2				srcStageMask				= VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
736		VkPipelineStageFlags2				dstStageMask				= VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR;
737#endif // CTS_USES_VULKANSC
738		deUint32							memoryBarrierCount			= pDependencyInfo->memoryBarrierCount;
739		deUint32							bufferMemoryBarrierCount	= pDependencyInfo->bufferMemoryBarrierCount;
740		deUint32							imageMemoryBarrierCount		= pDependencyInfo->imageMemoryBarrierCount;
741		VkMemoryBarrier*					pMemoryBarriers				= DE_NULL;
742		VkBufferMemoryBarrier*				pBufferMemoryBarriers		= DE_NULL;
743		VkImageMemoryBarrier*				pImageMemoryBarriers		= DE_NULL;
744		std::vector<VkMemoryBarrier>		memoryBarriers;
745		std::vector<VkBufferMemoryBarrier>	bufferMemoryBarriers;
746		std::vector<VkImageMemoryBarrier>	imageMemoryBarriers;
747
748		if (pDependencyInfo->pMemoryBarriers)
749		{
750			srcStageMask = pDependencyInfo->pMemoryBarriers[0].srcStageMask;
751			dstStageMask = pDependencyInfo->pMemoryBarriers[0].dstStageMask;
752
753			memoryBarriers.reserve(memoryBarrierCount);
754			for (deUint32 i = 0; i < memoryBarrierCount; ++i)
755			{
756				const VkMemoryBarrier2& mb = pDependencyInfo->pMemoryBarriers[i];
757				DE_ASSERT(isAccessFlagAllowed(mb.srcAccessMask));
758				DE_ASSERT(isAccessFlagAllowed(mb.dstAccessMask));
759				memoryBarriers.push_back(
760					makeMemoryBarrier(
761						static_cast<VkAccessFlags>(mb.srcAccessMask),
762						static_cast<VkAccessFlags>(mb.dstAccessMask)
763					)
764				);
765			}
766			pMemoryBarriers = &memoryBarriers[0];
767		}
768		if (pDependencyInfo->pBufferMemoryBarriers)
769		{
770			srcStageMask = pDependencyInfo->pBufferMemoryBarriers[0].srcStageMask;
771			dstStageMask = pDependencyInfo->pBufferMemoryBarriers[0].dstStageMask;
772
773			bufferMemoryBarriers.reserve(bufferMemoryBarrierCount);
774			for (deUint32 i = 0; i < bufferMemoryBarrierCount; ++i)
775			{
776				const VkBufferMemoryBarrier2& bmb = pDependencyInfo->pBufferMemoryBarriers[i];
777				DE_ASSERT(isAccessFlagAllowed(bmb.srcAccessMask));
778				DE_ASSERT(isAccessFlagAllowed(bmb.dstAccessMask));
779				bufferMemoryBarriers.push_back(
780					makeBufferMemoryBarrier(
781						static_cast<VkAccessFlags>(bmb.srcAccessMask),
782						static_cast<VkAccessFlags>(bmb.dstAccessMask),
783						bmb.buffer,
784						bmb.offset,
785						bmb.size,
786						bmb.srcQueueFamilyIndex,
787						bmb.dstQueueFamilyIndex
788					)
789				);
790			}
791			pBufferMemoryBarriers = &bufferMemoryBarriers[0];
792		}
793		if (pDependencyInfo->pImageMemoryBarriers)
794		{
795			srcStageMask = pDependencyInfo->pImageMemoryBarriers[0].srcStageMask;
796			dstStageMask = pDependencyInfo->pImageMemoryBarriers[0].dstStageMask;
797
798			imageMemoryBarriers.reserve(imageMemoryBarrierCount);
799			for (deUint32 i = 0; i < imageMemoryBarrierCount; ++i)
800			{
801				const VkImageMemoryBarrier2& imb = pDependencyInfo->pImageMemoryBarriers[i];
802				DE_ASSERT(isAccessFlagAllowed(imb.srcAccessMask));
803				DE_ASSERT(isAccessFlagAllowed(imb.dstAccessMask));
804				imageMemoryBarriers.push_back(
805					makeImageMemoryBarrier(
806						static_cast<VkAccessFlags>(imb.srcAccessMask),
807						static_cast<VkAccessFlags>(imb.dstAccessMask),
808						imb.oldLayout,
809						imb.newLayout,
810						imb.image,
811						imb.subresourceRange,
812						imb.srcQueueFamilyIndex,
813						imb.dstQueueFamilyIndex
814					)
815				);
816			}
817			pImageMemoryBarriers = &imageMemoryBarriers[0];
818		}
819
820		DE_ASSERT(isStageFlagAllowed(srcStageMask));
821		DE_ASSERT(isStageFlagAllowed(dstStageMask));
822		m_vk.cmdWaitEvents(commandBuffer, eventCount, pEvents,
823			static_cast<VkPipelineStageFlags>(srcStageMask), static_cast<VkPipelineStageFlags>(dstStageMask),
824			memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
825	}
826
827	VkResult queueSubmit(VkQueue queue, VkFence fence) override
828	{
829		// make sure submit info was added
830		DE_ASSERT(!m_submitInfoData.empty());
831
832		// make sure separate LegacySynchronizationWrapper is created per single submit
833		DE_ASSERT(!m_submited);
834
835		std::vector<VkSubmitInfo> submitInfo(m_submitInfoData.size(), { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 0u, DE_NULL, DE_NULL, 0u, DE_NULL, 0u, DE_NULL });
836
837		std::vector<VkTimelineSemaphoreSubmitInfo> timelineSemaphoreSubmitInfo;
838		timelineSemaphoreSubmitInfo.reserve(m_submitInfoData.size());
839
840		// translate indexes from m_submitInfoData to pointers and construct VkSubmitInfo
841		for (deUint32 i = 0; i < m_submitInfoData.size(); ++i)
842		{
843			auto&			data	= m_submitInfoData[i];
844			VkSubmitInfo&	si		= submitInfo[i];
845
846			si.waitSemaphoreCount	= data.waitSemaphoreCount;
847			si.commandBufferCount	= data.commandBufferCount;
848			si.signalSemaphoreCount	= data.signalSemaphoreCount;
849
850			if (data.waitSemaphoreValueIndexPlusOne || data.signalSemaphoreValueIndexPlusOne)
851			{
852				deUint64* pWaitSemaphoreValues = DE_NULL;
853				if (data.waitSemaphoreValueIndexPlusOne)
854					pWaitSemaphoreValues = &m_timelineSemaphoreValues[data.waitSemaphoreValueIndexPlusOne - 1];
855
856				deUint64* pSignalSemaphoreValues = DE_NULL;
857				if (data.signalSemaphoreValueIndexPlusOne)
858					pSignalSemaphoreValues = &m_timelineSemaphoreValues[data.signalSemaphoreValueIndexPlusOne - 1];
859
860				timelineSemaphoreSubmitInfo.push_back({
861					VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,		// VkStructureType	sType;
862					DE_NULL,												// const void*		pNext;
863					data.waitSemaphoreCount,								// deUint32			waitSemaphoreValueCount
864					pWaitSemaphoreValues,									// const deUint64*	pWaitSemaphoreValues
865					data.signalSemaphoreCount,								// deUint32			signalSemaphoreValueCount
866					pSignalSemaphoreValues									// const deUint64*	pSignalSemaphoreValues
867				});
868				si.pNext = &timelineSemaphoreSubmitInfo.back();
869			}
870
871			if (data.waitSemaphoreCount)
872			{
873				si.pWaitSemaphores		= &m_waitSemaphores[data.waitSemaphoreIndex];
874				si.pWaitDstStageMask	= &m_waitDstStageMasks[data.waitSemaphoreIndex];
875			}
876
877			if (data.commandBufferCount)
878				si.pCommandBuffers = &m_commandBuffers[data.commandBufferIndex];
879
880			if (data.signalSemaphoreCount)
881				si.pSignalSemaphores = &m_signalSemaphores[data.signalSemaphoreIndex];
882		}
883
884		m_submited = DE_TRUE;
885		return m_vk.queueSubmit(queue, static_cast<deUint32>(submitInfo.size()), &submitInfo[0], fence);
886	}
887
888protected:
889
890	std::vector<VkSemaphore>			m_waitSemaphores;
891	std::vector<VkSemaphore>			m_signalSemaphores;
892	std::vector<VkPipelineStageFlags>	m_waitDstStageMasks;
893	std::vector<VkCommandBuffer>		m_commandBuffers;
894	std::vector<SubmitInfoData>			m_submitInfoData;
895	std::vector<deUint64>				m_timelineSemaphoreValues;
896	bool								m_submited;
897};
898
899class Synchronization2Wrapper : public SynchronizationWrapperBase
900{
901public:
902	Synchronization2Wrapper(const DeviceInterface& vk, deUint32 submitInfoCount)
903		: SynchronizationWrapperBase(vk)
904	{
905		m_submitInfo.reserve(submitInfoCount);
906	}
907
908	~Synchronization2Wrapper() = default;
909
910	void addSubmitInfo(deUint32								waitSemaphoreInfoCount,
911					   const VkSemaphoreSubmitInfo*			pWaitSemaphoreInfos,
912					   deUint32								commandBufferInfoCount,
913					   const VkCommandBufferSubmitInfo*		pCommandBufferInfos,
914					   deUint32								signalSemaphoreInfoCount,
915					   const VkSemaphoreSubmitInfo*			pSignalSemaphoreInfos,
916					   bool									usingWaitTimelineSemaphore,
917					   bool									usingSignalTimelineSemaphore) override
918	{
919		DE_UNREF(usingWaitTimelineSemaphore);
920		DE_UNREF(usingSignalTimelineSemaphore);
921
922		m_submitInfo.push_back(VkSubmitInfo2{
923#ifndef CTS_USES_VULKANSC
924			VK_STRUCTURE_TYPE_SUBMIT_INFO_2,			// VkStructureType						sType
925#else
926			VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR,		// VkStructureType						sType
927#endif // CTS_USES_VULKANSC
928			DE_NULL,									// const void*							pNext
929			0u,											// VkSubmitFlags						flags
930			waitSemaphoreInfoCount,						// deUint32								waitSemaphoreInfoCount
931			pWaitSemaphoreInfos,						// const VkSemaphoreSubmitInfo*			pWaitSemaphoreInfos
932			commandBufferInfoCount,						// deUint32								commandBufferInfoCount
933			pCommandBufferInfos,						// const VkCommandBufferSubmitInfo*		pCommandBufferInfos
934			signalSemaphoreInfoCount,					// deUint32								signalSemaphoreInfoCount
935			pSignalSemaphoreInfos						// const VkSemaphoreSubmitInfo*			pSignalSemaphoreInfos
936		});
937	}
938
939	void cmdPipelineBarrier(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo) const override
940	{
941#ifndef CTS_USES_VULKANSC
942		m_vk.cmdPipelineBarrier2(commandBuffer, pDependencyInfo);
943#else
944		m_vk.cmdPipelineBarrier2KHR(commandBuffer, pDependencyInfo);
945#endif // CTS_USES_VULKANSC
946	}
947
948	void cmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo) const override
949	{
950#ifndef CTS_USES_VULKANSC
951		m_vk.cmdSetEvent2(commandBuffer, event, pDependencyInfo);
952#else
953		m_vk.cmdSetEvent2KHR(commandBuffer, event, pDependencyInfo);
954#endif // CTS_USES_VULKANSC
955	}
956
957	void cmdWaitEvents(VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfo) const override
958	{
959#ifndef CTS_USES_VULKANSC
960		m_vk.cmdWaitEvents2(commandBuffer, eventCount, pEvents, pDependencyInfo);
961#else
962		m_vk.cmdWaitEvents2KHR(commandBuffer, eventCount, pEvents, pDependencyInfo);
963#endif // CTS_USES_VULKANSC
964	}
965
966	void cmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 flag) const override
967	{
968#ifndef CTS_USES_VULKANSC
969		m_vk.cmdResetEvent2(commandBuffer, event, flag);
970#else
971		m_vk.cmdResetEvent2KHR(commandBuffer, event, flag);
972#endif // CTS_USES_VULKANSC
973	}
974
975	VkResult queueSubmit(VkQueue queue, VkFence fence) override
976	{
977#ifndef CTS_USES_VULKANSC
978		return m_vk.queueSubmit2(queue, static_cast<deUint32>(m_submitInfo.size()), &m_submitInfo[0], fence);
979#else
980		return m_vk.queueSubmit2KHR(queue, static_cast<deUint32>(m_submitInfo.size()), &m_submitInfo[0], fence);
981#endif // CTS_USES_VULKANSC
982	}
983
984protected:
985
986	std::vector<VkSubmitInfo2> m_submitInfo;
987};
988
989SynchronizationWrapperPtr getSynchronizationWrapper(SynchronizationType		type,
990													const DeviceInterface&	vk,
991													bool					usingTimelineSemaphores,
992													deUint32				submitInfoCount)
993{
994	return (type == SynchronizationType::LEGACY)
995		? SynchronizationWrapperPtr(new LegacySynchronizationWrapper(vk, usingTimelineSemaphores, submitInfoCount))
996		: SynchronizationWrapperPtr(new Synchronization2Wrapper(vk, submitInfoCount));
997}
998
999void submitCommandsAndWait(SynchronizationWrapperPtr	synchronizationWrapper,
1000						   const DeviceInterface&		vk,
1001						   const VkDevice				device,
1002						   const VkQueue				queue,
1003						   const VkCommandBuffer		cmdBuffer)
1004{
1005	VkCommandBufferSubmitInfo commandBufferInfoCount = makeCommonCommandBufferSubmitInfo(cmdBuffer);
1006
1007	synchronizationWrapper->addSubmitInfo(
1008		0u,										// deUint32								waitSemaphoreInfoCount
1009		DE_NULL,								// const VkSemaphoreSubmitInfo*			pWaitSemaphoreInfos
1010		1u,										// deUint32								commandBufferInfoCount
1011		&commandBufferInfoCount,				// const VkCommandBufferSubmitInfo*		pCommandBufferInfos
1012		0u,										// deUint32								signalSemaphoreInfoCount
1013		DE_NULL									// const VkSemaphoreSubmitInfo*			pSignalSemaphoreInfos
1014	);
1015
1016	const Unique<VkFence> fence(createFence(vk, device));
1017	VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
1018	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
1019}
1020
1021void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
1022{
1023	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1024
1025	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
1026		throw tcu::NotSupportedError("Tessellation shader not supported");
1027
1028	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
1029		throw tcu::NotSupportedError("Geometry shader not supported");
1030
1031	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
1032		throw tcu::NotSupportedError("Double-precision floats not supported");
1033
1034	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
1035		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
1036
1037	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
1038		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
1039
1040	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
1041		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
1042}
1043
1044void requireStorageImageSupport(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat fmt, const VkImageTiling tiling)
1045{
1046	const VkFormatProperties	p			= getPhysicalDeviceFormatProperties(vki, physDevice, fmt);
1047	const auto&					features	= ((tiling == VK_IMAGE_TILING_LINEAR) ? p.linearTilingFeatures : p.optimalTilingFeatures);
1048
1049	if ((features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
1050		throw tcu::NotSupportedError("Storage image format not supported");
1051}
1052
1053std::string getResourceName (const ResourceDescription& resource)
1054{
1055	std::ostringstream str;
1056
1057	if ((resource.type == RESOURCE_TYPE_BUFFER) ||
1058		(resource.type == RESOURCE_TYPE_INDEX_BUFFER))
1059	{
1060		str << "buffer_" << resource.size.x();
1061	}
1062	else if (resource.type == RESOURCE_TYPE_IMAGE)
1063	{
1064		str << "image_" << resource.size.x()
1065						<< (resource.size.y() > 0 ? "x" + de::toString(resource.size.y()) : "")
1066						<< (resource.size.z() > 0 ? "x" + de::toString(resource.size.z()) : "")
1067			<< "_" << de::toLower(getFormatName(resource.imageFormat)).substr(10);
1068	}
1069	else if (isIndirectBuffer(resource.type))
1070		str << "indirect_buffer";
1071	else
1072		DE_ASSERT(0);
1073
1074	return str.str();
1075}
1076
1077bool isIndirectBuffer (const ResourceType type)
1078{
1079	switch (type)
1080	{
1081		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
1082		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
1083		case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
1084			return true;
1085
1086		default:
1087			return false;
1088	}
1089}
1090
1091VkCommandBufferSubmitInfo makeCommonCommandBufferSubmitInfo (const VkCommandBuffer cmdBuf)
1092{
1093	return
1094	{
1095#ifndef CTS_USES_VULKANSC
1096		VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,		// VkStructureType		sType
1097#else
1098		VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR,	// VkStructureType		sType
1099#endif // CTS_USES_VULKANSC
1100		DE_NULL,											// const void*			pNext
1101		cmdBuf,												// VkCommandBuffer		commandBuffer
1102		0u													// uint32_t				deviceMask
1103	};
1104}
1105
1106VkSemaphoreSubmitInfo makeCommonSemaphoreSubmitInfo(VkSemaphore semaphore, deUint64 value, VkPipelineStageFlags2 stageMask)
1107{
1108	return
1109	{
1110#ifndef CTS_USES_VULKANSC
1111		VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,		// VkStructureType				sType
1112#else
1113		VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,	// VkStructureType				sType
1114#endif // CTS_USES_VULKANSC
1115		DE_NULL,										// const void*					pNext
1116		semaphore,										// VkSemaphore					semaphore
1117		value,											// deUint64						value
1118		stageMask,										// VkPipelineStageFlags2		stageMask
1119		0u												// deUint32						deviceIndex
1120	};
1121}
1122
1123VkDependencyInfo makeCommonDependencyInfo(const VkMemoryBarrier2* pMemoryBarrier, const VkBufferMemoryBarrier2* pBufferMemoryBarrier, const VkImageMemoryBarrier2* pImageMemoryBarrier,
1124                                                                                   bool eventDependency)
1125{
1126	return
1127	{
1128#ifndef CTS_USES_VULKANSC
1129		VK_STRUCTURE_TYPE_DEPENDENCY_INFO,					// VkStructureType					sType
1130#else
1131		VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,				// VkStructureType					sType
1132#endif // CTS_USES_VULKANSC
1133		DE_NULL,											// const void*						pNext
1134		eventDependency ? (VkDependencyFlags)0u : (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT,	// VkDependencyFlags				dependencyFlags
1135		!!pMemoryBarrier,									// deUint32							memoryBarrierCount
1136		pMemoryBarrier,										// const VkMemoryBarrier2KHR*		pMemoryBarriers
1137		!!pBufferMemoryBarrier,								// deUint32							bufferMemoryBarrierCount
1138		pBufferMemoryBarrier,								// const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers
1139		!!pImageMemoryBarrier,								// deUint32							imageMemoryBarrierCount
1140		pImageMemoryBarrier									// const VkImageMemoryBarrier2KHR*	pImageMemoryBarriers
1141	};
1142}
1143
1144PipelineCacheData::PipelineCacheData (void)
1145{
1146}
1147
1148PipelineCacheData::~PipelineCacheData (void)
1149{
1150}
1151
1152vk::Move<VkPipelineCache> PipelineCacheData::createPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device, de::SharedPtr<vk::ResourceInterface> resourceInterface) const
1153{
1154#ifndef CTS_USES_VULKANSC
1155	DE_UNREF(resourceInterface);
1156#endif
1157	const de::ScopedLock						dataLock	(m_lock);
1158	const struct vk::VkPipelineCacheCreateInfo	params	=
1159	{
1160		vk::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
1161		DE_NULL,
1162#ifndef CTS_USES_VULKANSC
1163		(vk::VkPipelineCacheCreateFlags)0,
1164		(deUintptr)m_data.size(),
1165		(m_data.empty() ? DE_NULL : &m_data[0])
1166#else
1167		VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
1168			VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,
1169		resourceInterface->getCacheDataSize(),	// deUintptr					initialDataSize;
1170		resourceInterface->getCacheData()		// const void*					pInitialData;
1171#endif // CTS_USES_VULKANSC
1172	};
1173
1174	return vk::createPipelineCache(vk, device, &params);
1175}
1176
1177void PipelineCacheData::setFromPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache)
1178{
1179	const de::ScopedLock		dataLock		(m_lock);
1180
1181#ifndef CTS_USES_VULKANSC
1182	deUintptr					dataSize = 0;
1183	VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, DE_NULL));
1184
1185	m_data.resize(dataSize);
1186
1187	if (dataSize > 0)
1188		VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, &m_data[0]));
1189#else
1190	DE_UNREF(vk);
1191	DE_UNREF(device);
1192	DE_UNREF(pipelineCache);
1193#endif
1194}
1195
1196vk::VkDevice getSyncDevice (de::MovePtr<VideoDevice>& device, Context& context)
1197{
1198	if (device == DE_NULL)
1199		return context.getDevice();
1200	else
1201		return device->getDeviceSupportingQueue();
1202}
1203
1204const vk::DeviceInterface& getSyncDeviceInterface (de::MovePtr<VideoDevice>& device, Context& context)
1205{
1206	if (device == DE_NULL)
1207		return context.getDeviceInterface();
1208	else
1209		return device->getDeviceDriver();
1210}
1211
1212deUint32 getSyncQueueFamilyIndex (de::MovePtr<VideoDevice>& device, Context& context)
1213{
1214	if (device == DE_NULL)
1215		return context.getUniversalQueueFamilyIndex();
1216	else
1217		return device->getQueueFamilyVideo();
1218}
1219
1220vk::VkQueue getSyncQueue (de::MovePtr<VideoDevice>& device, Context& context)
1221{
1222	if (device == DE_NULL)
1223		return context.getUniversalQueue();
1224	else
1225		return getDeviceQueue(device->getDeviceDriver(), device->getDeviceSupportingQueue(), device->getQueueFamilyVideo(), 0u);
1226}
1227
1228} // synchronization
1229} // vkt
1230