• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _VKTSYNCHRONIZATIONUTIL_HPP
2 #define _VKTSYNCHRONIZATIONUTIL_HPP
3 /*------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2016 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Synchronization tests utilities
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vkDefs.hpp"
27 #include "vkObjUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPrograms.hpp"
32 #include "tcuVector.hpp"
33 #include "deMutex.hpp"
34 #include <memory>
35 #include "vkResourceInterface.hpp"
36 #include "vktCustomInstancesDevices.hpp"
37 
38 namespace vkt
39 {
40 namespace synchronization
41 {
42 
43 enum class SynchronizationType
44 {
45 	LEGACY				= 0,
46 	SYNCHRONIZATION2,
47 };
48 
49 #ifdef CTS_USES_VULKANSC
50 	#define VkSemaphoreSubmitInfo		VkSemaphoreSubmitInfoKHR
51 	#define VkCommandBufferSubmitInfo	VkCommandBufferSubmitInfoKHR
52 	#define VkDependencyInfo			VkDependencyInfoKHR
53 	#define VkPipelineStageFlags2		VkPipelineStageFlags2KHR
54 	#define VkAccessFlags2				VkAccessFlags2KHR
55 	#define VkMemoryBarrier2			VkMemoryBarrier2KHR
56 	#define VkImageMemoryBarrier2		VkImageMemoryBarrier2KHR
57 	#define VkBufferMemoryBarrier2		VkBufferMemoryBarrier2KHR
58 	#define VkSubmitInfo2				VkSubmitInfo2KHR
59 #endif // CTS_USES_VULKANSC
60 
61 class Buffer
62 {
63 public:
Buffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo,const vk::MemoryRequirement memoryRequirement)64 										Buffer			(const vk::DeviceInterface&		vk,
65 														 const vk::VkDevice				device,
66 														 vk::Allocator&					allocator,
67 														 const vk::VkBufferCreateInfo&	bufferCreateInfo,
68 														 const vk::MemoryRequirement	memoryRequirement)
69 		: m_buffer		(createBuffer(vk, device, &bufferCreateInfo))
70 		, m_allocation	(allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement))
71 	{
72 		VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
73 	}
74 
Buffer(vk::Move<vk::VkBuffer> buffer,de::MovePtr<vk::Allocation> allocation)75 										Buffer			(vk::Move<vk::VkBuffer>			buffer,
76 														 de::MovePtr<vk::Allocation>	allocation)
77 		: m_buffer		(buffer)
78 		, m_allocation	(allocation)
79 	{
80 	}
81 
get(void) const82 	const vk::VkBuffer&					get				(void) const { return *m_buffer; }
operator *(void) const83 	const vk::VkBuffer&					operator*		(void) const { return get(); }
getAllocation(void) const84 	vk::Allocation&						getAllocation	(void) const { return *m_allocation; }
85 
86 private:
87 	const vk::Unique<vk::VkBuffer>		m_buffer;
88 	const de::UniquePtr<vk::Allocation>	m_allocation;
89 
90 	// "deleted"
91 										Buffer			(const Buffer&);
92 	Buffer&								operator=		(const Buffer&);
93 };
94 
95 class Image
96 {
97 public:
Image(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkImageCreateInfo & imageCreateInfo,const vk::MemoryRequirement memoryRequirement)98 										Image			(const vk::DeviceInterface&		vk,
99 														 const vk::VkDevice				device,
100 														 vk::Allocator&					allocator,
101 														 const vk::VkImageCreateInfo&	imageCreateInfo,
102 														 const vk::MemoryRequirement	memoryRequirement)
103 		: m_image		(createImage(vk, device, &imageCreateInfo))
104 		, m_allocation	(allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement))
105 	{
106 		VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset()));
107 	}
Image(vk::Move<vk::VkImage> & image,de::MovePtr<vk::Allocation> & allocation)108 										Image			(vk::Move<vk::VkImage>&			image,
109 														 de::MovePtr<vk::Allocation>&	allocation)
110 		: m_image		(image)
111 		, m_allocation	(allocation)
112 	{
113 	}
114 
get(void) const115 	const vk::VkImage&					get				(void) const { return *m_image; }
operator *(void) const116 	const vk::VkImage&					operator*		(void) const { return get(); }
getAllocation(void) const117 	vk::Allocation&						getAllocation	(void) const { return *m_allocation; }
118 
119 private:
120 	const vk::Unique<vk::VkImage>		m_image;
121 	const de::UniquePtr<vk::Allocation>	m_allocation;
122 
123 	// "deleted"
124 										Image			(const Image&);
125 	Image&								operator=		(const Image&);
126 };
127 
128 class PipelineCacheData
129 {
130 public:
131 									PipelineCacheData		(void);
132 									~PipelineCacheData		(void);
133 
134 	vk::Move<vk::VkPipelineCache>	createPipelineCache		(const vk::DeviceInterface& vk, const vk::VkDevice device, de::SharedPtr<vk::ResourceInterface> resourceInterface) const;
135 	void							setFromPipelineCache	(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache);
136 
137 private:
138 	mutable de::Mutex				m_lock;
139 	std::vector<deUint8>			m_data;
140 };
141 
142 class GraphicsPipelineBuilder
143 {
144 public:
GraphicsPipelineBuilder(void)145 								GraphicsPipelineBuilder	(void) : m_renderSize			(0, 0)
146 															   , m_shaderStageFlags		(0u)
147 															   , m_cullModeFlags		(vk::VK_CULL_MODE_NONE)
148 															   , m_frontFace			(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
149 															   , m_patchControlPoints	(1u)
150 															   , m_blendEnable			(false)
151 															   , m_primitiveTopology	(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) {}
152 
setRenderSize(const tcu::IVec2 & size)153 	GraphicsPipelineBuilder&	setRenderSize					(const tcu::IVec2& size) { m_renderSize = size; return *this; }
154 	GraphicsPipelineBuilder&	setShader						(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkShaderStageFlagBits stage, const vk::ProgramBinary& binary, const vk::VkSpecializationInfo* specInfo);
setPatchControlPoints(const deUint32 controlPoints)155 	GraphicsPipelineBuilder&	setPatchControlPoints			(const deUint32 controlPoints) { m_patchControlPoints = controlPoints; return *this; }
setCullModeFlags(const vk::VkCullModeFlags cullModeFlags)156 	GraphicsPipelineBuilder&	setCullModeFlags				(const vk::VkCullModeFlags cullModeFlags) { m_cullModeFlags = cullModeFlags; return *this; }
setFrontFace(const vk::VkFrontFace frontFace)157 	GraphicsPipelineBuilder&	setFrontFace					(const vk::VkFrontFace frontFace) { m_frontFace = frontFace; return *this; }
setBlend(const bool enable)158 	GraphicsPipelineBuilder&	setBlend						(const bool enable) { m_blendEnable = enable; return *this; }
159 
160 	//! Applies only to pipelines without tessellation shaders.
setPrimitiveTopology(const vk::VkPrimitiveTopology topology)161 	GraphicsPipelineBuilder&	setPrimitiveTopology			(const vk::VkPrimitiveTopology topology) { m_primitiveTopology = topology; return *this; }
162 
addVertexBinding(const vk::VkVertexInputBindingDescription vertexBinding)163 	GraphicsPipelineBuilder&	addVertexBinding				(const vk::VkVertexInputBindingDescription vertexBinding) { m_vertexInputBindings.push_back(vertexBinding); return *this; }
addVertexAttribute(const vk::VkVertexInputAttributeDescription vertexAttribute)164 	GraphicsPipelineBuilder&	addVertexAttribute				(const vk::VkVertexInputAttributeDescription vertexAttribute) { m_vertexInputAttributes.push_back(vertexAttribute); return *this; }
165 
166 	//! Basic vertex input configuration (uses biding 0, location 0, etc.)
167 	GraphicsPipelineBuilder&	setVertexInputSingleAttribute	(const vk::VkFormat vertexFormat, const deUint32 stride);
168 
169 	vk::Move<vk::VkPipeline>	build(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkRenderPass renderPass, PipelineCacheData& pipelineCacheData, de::SharedPtr<vk::ResourceInterface> resourceInterface);
170 
171 private:
172 	tcu::IVec2											m_renderSize;
173 	vk::Move<vk::VkShaderModule>						m_vertexShaderModule;
174 	vk::Move<vk::VkShaderModule>						m_fragmentShaderModule;
175 	vk::Move<vk::VkShaderModule>						m_geometryShaderModule;
176 	vk::Move<vk::VkShaderModule>						m_tessControlShaderModule;
177 	vk::Move<vk::VkShaderModule>						m_tessEvaluationShaderModule;
178 	std::vector<vk::VkPipelineShaderStageCreateInfo>	m_shaderStages;
179 	std::vector<vk::VkVertexInputBindingDescription>	m_vertexInputBindings;
180 	std::vector<vk::VkVertexInputAttributeDescription>	m_vertexInputAttributes;
181 	vk::VkShaderStageFlags								m_shaderStageFlags;
182 	vk::VkCullModeFlags									m_cullModeFlags;
183 	vk::VkFrontFace										m_frontFace;
184 	deUint32											m_patchControlPoints;
185 	bool												m_blendEnable;
186 	vk::VkPrimitiveTopology								m_primitiveTopology;
187 
188 	GraphicsPipelineBuilder (const GraphicsPipelineBuilder&); // "deleted"
189 	GraphicsPipelineBuilder& operator= (const GraphicsPipelineBuilder&);
190 };
191 
192 // Base class that abstracts over legacy synchronization and synchronization changes
193 // introduced with VK_KHR_synchronization2 extension. Since structures in
194 // VK_KHR_synchronization2 have more features this wrapper uses them and when legacy
195 // implementation is used in tests then data from new structures is used to fill legacy ones.
196 class SynchronizationWrapperBase
197 {
198 public:
SynchronizationWrapperBase(const vk::DeviceInterface & vk)199 	SynchronizationWrapperBase(const vk::DeviceInterface& vk)
200 		: m_vk(vk)
201 	{}
202 
203 	virtual ~SynchronizationWrapperBase() = default;
204 
205 	virtual void			addSubmitInfo		(deUint32									waitSemaphoreInfoCount,
206 												 const vk::VkSemaphoreSubmitInfo*			pWaitSemaphoreInfos,
207 												 deUint32									commandBufferInfoCount,
208 												 const vk::VkCommandBufferSubmitInfo*		pCommandBufferInfos,
209 												 deUint32									signalSemaphoreInfoCount,
210 												 const vk::VkSemaphoreSubmitInfo*			pSignalSemaphoreInfos,
211 												 bool										usingWaitTimelineSemaphore = DE_FALSE,
212 												 bool										usingSignalTimelineSemaphore = DE_FALSE) = 0;
213 
214 	virtual void			cmdPipelineBarrier	(vk::VkCommandBuffer						commandBuffer,
215 												 const vk::VkDependencyInfo*				pDependencyInfo) const = 0;
216 
217 	virtual void			cmdSetEvent			(vk::VkCommandBuffer						commandBuffer,
218 												 vk::VkEvent								event,
219 												 const vk::VkDependencyInfo*				pDependencyInfo) const = 0;
220 	virtual void			cmdResetEvent		(vk::VkCommandBuffer						commandBuffer,
221 												 vk::VkEvent								event,
222 												 vk::VkPipelineStageFlags2					flag) const = 0;
223 	virtual void			cmdWaitEvents		(vk::VkCommandBuffer						commandBuffer,
224 												 deUint32									eventCount,
225 												 const vk::VkEvent*							pEvents,
226 												 const vk::VkDependencyInfo*				pDependencyInfo) const = 0;
227 
228 	virtual vk::VkResult	queueSubmit			(vk::VkQueue								queue,
229 												 vk::VkFence								fence) = 0;
230 
231 protected:
232 	const vk::DeviceInterface& m_vk;
233 };
234 
235 enum FeatureFlagBits
236 {
237 	FEATURE_TESSELLATION_SHADER							= 1u << 0,
238 	FEATURE_GEOMETRY_SHADER								= 1u << 1,
239 	FEATURE_SHADER_FLOAT_64								= 1u << 2,
240 	FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS			= 1u << 3,
241 	FEATURE_FRAGMENT_STORES_AND_ATOMICS					= 1u << 4,
242 	FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE	= 1u << 5,
243 };
244 typedef deUint32 FeatureFlags;
245 
246 enum SyncPrimitive
247 {
248 	SYNC_PRIMITIVE_FENCE,
249 	SYNC_PRIMITIVE_BINARY_SEMAPHORE,
250 	SYNC_PRIMITIVE_TIMELINE_SEMAPHORE,
251 	SYNC_PRIMITIVE_BARRIER,
252 	SYNC_PRIMITIVE_EVENT,
253 };
254 
255 enum ResourceType
256 {
257 	RESOURCE_TYPE_BUFFER,
258 	RESOURCE_TYPE_IMAGE,
259 	RESOURCE_TYPE_INDIRECT_BUFFER_DRAW,
260 	RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED,
261 	RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH,
262 	RESOURCE_TYPE_INDEX_BUFFER,
263 };
264 
265 struct ResourceDescription
266 {
267 	ResourceType					type;
268 	tcu::IVec4						size;			//!< unused components are 0, e.g. for buffers only x is meaningful
269 	vk::VkImageType					imageType;
270 	vk::VkFormat					imageFormat;
271 	vk::VkImageAspectFlags			imageAspect;
272 	vk::VkSampleCountFlagBits		imageSamples;
273 };
274 
275 struct BufferResource
276 {
BufferResourcevkt::synchronization::BufferResource277 	BufferResource (vk::VkBuffer handle_, vk::VkDeviceSize offset_, vk::VkDeviceSize size_)
278 		: handle(handle_), offset(offset_), size(size_)
279 		{}
280 
281 	vk::VkBuffer					handle;
282 	vk::VkDeviceSize				offset;
283 	vk::VkDeviceSize				size;
284 };
285 
286 struct ImageResource
287 {
ImageResourcevkt::synchronization::ImageResource288 	ImageResource (
289 		vk::VkImage handle_,
290 		vk::VkExtent3D extent_,
291 		vk::VkImageType imageType_,
292 		vk::VkFormat format_,
293 		vk::VkImageSubresourceRange subresourceRange_,
294 		vk::VkImageSubresourceLayers subresourceLayers_,
295 		vk::VkImageTiling tiling_)
296 		: handle(handle_)
297 		, extent(extent_)
298 		, imageType(imageType_)
299 		, format(format_)
300 		, subresourceRange(subresourceRange_)
301 		, subresourceLayers(subresourceLayers_)
302 		, tiling(tiling_)
303 		{}
304 
305 	vk::VkImage						handle;
306 	vk::VkExtent3D					extent;
307 	vk::VkImageType					imageType;
308 	vk::VkFormat					format;
309 	vk::VkImageSubresourceRange		subresourceRange;
310 	vk::VkImageSubresourceLayers	subresourceLayers;
311 	vk::VkImageTiling				tiling;
312 };
313 
314 typedef std::shared_ptr<SynchronizationWrapperBase> SynchronizationWrapperPtr;
315 SynchronizationWrapperPtr			getSynchronizationWrapper					(SynchronizationType				type,
316 																				 const vk::DeviceInterface&			vk,
317 																				 bool								usingTimelineSemaphores,
318 																				 deUint32							submitInfoCount = 1u);
319 void								submitCommandsAndWait						(SynchronizationWrapperPtr			synchronizationWrapper,
320 																				 const vk::DeviceInterface&			vk,
321 																				 const vk::VkDevice					device,
322 																				 const vk::VkQueue					queue,
323 																				 const vk::VkCommandBuffer			cmdBuffer);
324 vk::VkImageCreateInfo				makeImageCreateInfo							(const vk::VkImageType				imageType,
325 																				 const vk::VkExtent3D&				extent,
326 																				 const vk::VkFormat					format,
327 																				 const vk::VkImageUsageFlags		usage,
328 																				 const vk::VkSampleCountFlagBits	samples,
329 																				 const vk::VkImageTiling			tiling);
330 vk::Move<vk::VkCommandBuffer>		makeCommandBuffer							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool);
331 vk::Move<vk::VkPipeline>			makeComputePipeline							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkShaderModule shaderModule, const vk::VkSpecializationInfo* specInfo, PipelineCacheData& pipelineCacheData, de::SharedPtr<vk::ResourceInterface> resourceInterface);
332 void								beginRenderPassWithRasterizationDisabled	(const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer);
333 void								requireFeatures								(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const FeatureFlags flags);
334 void								requireStorageImageSupport					(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const vk::VkFormat fmt, const vk::VkImageTiling tiling);
335 std::string							getResourceName								(const ResourceDescription& resource);
336 bool								isIndirectBuffer							(const ResourceType type);
337 vk::VkCommandBufferSubmitInfoKHR	makeCommonCommandBufferSubmitInfo			(const vk::VkCommandBuffer cmdBuf);
338 vk::VkSemaphoreSubmitInfoKHR		makeCommonSemaphoreSubmitInfo				(vk::VkSemaphore semaphore, deUint64 value, vk::VkPipelineStageFlags2KHR stageMask);
339 vk::VkDependencyInfoKHR				makeCommonDependencyInfo					(const vk::VkMemoryBarrier2KHR* pMemoryBarrier = DE_NULL, const vk::VkBufferMemoryBarrier2KHR* pBufferMemoryBarrier = DE_NULL, const vk::VkImageMemoryBarrier2KHR* pImageMemoryBarrier = DE_NULL, bool eventDependency = DE_FALSE);
340 
341 vk::VkDevice						getSyncDevice								(de::MovePtr<VideoDevice>& device, Context& context);
342 const vk::DeviceInterface&			getSyncDeviceInterface						(de::MovePtr<VideoDevice>& device, Context& context);
343 deUint32							getSyncQueueFamilyIndex						(de::MovePtr<VideoDevice>& device, Context& context);
344 vk::VkQueue							getSyncQueue								(de::MovePtr<VideoDevice>& device, Context& context);
345 } // synchronization
346 } // vkt
347 
348 #endif // _VKTSYNCHRONIZATIONUTIL_HPP
349