• 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 
36 namespace vkt
37 {
38 namespace synchronization
39 {
40 
41 enum class SynchronizationType
42 {
43 	LEGACY				= 0,
44 	SYNCHRONIZATION2,
45 };
46 
47 class Buffer
48 {
49 public:
Buffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo,const vk::MemoryRequirement memoryRequirement)50 										Buffer			(const vk::DeviceInterface&		vk,
51 														 const vk::VkDevice				device,
52 														 vk::Allocator&					allocator,
53 														 const vk::VkBufferCreateInfo&	bufferCreateInfo,
54 														 const vk::MemoryRequirement	memoryRequirement)
55 		: m_buffer		(createBuffer(vk, device, &bufferCreateInfo))
56 		, m_allocation	(allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement))
57 	{
58 		VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
59 	}
60 
Buffer(vk::Move<vk::VkBuffer> buffer,de::MovePtr<vk::Allocation> allocation)61 										Buffer			(vk::Move<vk::VkBuffer>			buffer,
62 														 de::MovePtr<vk::Allocation>	allocation)
63 		: m_buffer		(buffer)
64 		, m_allocation	(allocation)
65 	{
66 	}
67 
get(void) const68 	const vk::VkBuffer&					get				(void) const { return *m_buffer; }
operator *(void) const69 	const vk::VkBuffer&					operator*		(void) const { return get(); }
getAllocation(void) const70 	vk::Allocation&						getAllocation	(void) const { return *m_allocation; }
71 
72 private:
73 	const vk::Unique<vk::VkBuffer>		m_buffer;
74 	const de::UniquePtr<vk::Allocation>	m_allocation;
75 
76 	// "deleted"
77 										Buffer			(const Buffer&);
78 	Buffer&								operator=		(const Buffer&);
79 };
80 
81 class Image
82 {
83 public:
Image(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkImageCreateInfo & imageCreateInfo,const vk::MemoryRequirement memoryRequirement)84 										Image			(const vk::DeviceInterface&		vk,
85 														 const vk::VkDevice				device,
86 														 vk::Allocator&					allocator,
87 														 const vk::VkImageCreateInfo&	imageCreateInfo,
88 														 const vk::MemoryRequirement	memoryRequirement)
89 		: m_image		(createImage(vk, device, &imageCreateInfo))
90 		, m_allocation	(allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement))
91 	{
92 		VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset()));
93 	}
Image(vk::Move<vk::VkImage> & image,de::MovePtr<vk::Allocation> & allocation)94 										Image			(vk::Move<vk::VkImage>&			image,
95 														 de::MovePtr<vk::Allocation>&	allocation)
96 		: m_image		(image)
97 		, m_allocation	(allocation)
98 	{
99 	}
100 
get(void) const101 	const vk::VkImage&					get				(void) const { return *m_image; }
operator *(void) const102 	const vk::VkImage&					operator*		(void) const { return get(); }
getAllocation(void) const103 	vk::Allocation&						getAllocation	(void) const { return *m_allocation; }
104 
105 private:
106 	const vk::Unique<vk::VkImage>		m_image;
107 	const de::UniquePtr<vk::Allocation>	m_allocation;
108 
109 	// "deleted"
110 										Image			(const Image&);
111 	Image&								operator=		(const Image&);
112 };
113 
114 class PipelineCacheData
115 {
116 public:
117 									PipelineCacheData		(void);
118 									~PipelineCacheData		(void);
119 
120 	vk::Move<vk::VkPipelineCache>	createPipelineCache		(const vk::DeviceInterface& vk, const vk::VkDevice device) const;
121 	void							setFromPipelineCache	(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache);
122 
123 private:
124 	mutable de::Mutex				m_lock;
125 	std::vector<deUint8>			m_data;
126 };
127 
128 class GraphicsPipelineBuilder
129 {
130 public:
GraphicsPipelineBuilder(void)131 								GraphicsPipelineBuilder	(void) : m_renderSize			(0, 0)
132 															   , m_shaderStageFlags		(0u)
133 															   , m_cullModeFlags		(vk::VK_CULL_MODE_NONE)
134 															   , m_frontFace			(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
135 															   , m_patchControlPoints	(1u)
136 															   , m_blendEnable			(false)
137 															   , m_primitiveTopology	(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) {}
138 
setRenderSize(const tcu::IVec2 & size)139 	GraphicsPipelineBuilder&	setRenderSize					(const tcu::IVec2& size) { m_renderSize = size; return *this; }
140 	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)141 	GraphicsPipelineBuilder&	setPatchControlPoints			(const deUint32 controlPoints) { m_patchControlPoints = controlPoints; return *this; }
setCullModeFlags(const vk::VkCullModeFlags cullModeFlags)142 	GraphicsPipelineBuilder&	setCullModeFlags				(const vk::VkCullModeFlags cullModeFlags) { m_cullModeFlags = cullModeFlags; return *this; }
setFrontFace(const vk::VkFrontFace frontFace)143 	GraphicsPipelineBuilder&	setFrontFace					(const vk::VkFrontFace frontFace) { m_frontFace = frontFace; return *this; }
setBlend(const bool enable)144 	GraphicsPipelineBuilder&	setBlend						(const bool enable) { m_blendEnable = enable; return *this; }
145 
146 	//! Applies only to pipelines without tessellation shaders.
setPrimitiveTopology(const vk::VkPrimitiveTopology topology)147 	GraphicsPipelineBuilder&	setPrimitiveTopology			(const vk::VkPrimitiveTopology topology) { m_primitiveTopology = topology; return *this; }
148 
addVertexBinding(const vk::VkVertexInputBindingDescription vertexBinding)149 	GraphicsPipelineBuilder&	addVertexBinding				(const vk::VkVertexInputBindingDescription vertexBinding) { m_vertexInputBindings.push_back(vertexBinding); return *this; }
addVertexAttribute(const vk::VkVertexInputAttributeDescription vertexAttribute)150 	GraphicsPipelineBuilder&	addVertexAttribute				(const vk::VkVertexInputAttributeDescription vertexAttribute) { m_vertexInputAttributes.push_back(vertexAttribute); return *this; }
151 
152 	//! Basic vertex input configuration (uses biding 0, location 0, etc.)
153 	GraphicsPipelineBuilder&	setVertexInputSingleAttribute	(const vk::VkFormat vertexFormat, const deUint32 stride);
154 
155 	vk::Move<vk::VkPipeline>	build							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkRenderPass renderPass, PipelineCacheData& pipelineCacheData);
156 
157 private:
158 	tcu::IVec2											m_renderSize;
159 	vk::Move<vk::VkShaderModule>						m_vertexShaderModule;
160 	vk::Move<vk::VkShaderModule>						m_fragmentShaderModule;
161 	vk::Move<vk::VkShaderModule>						m_geometryShaderModule;
162 	vk::Move<vk::VkShaderModule>						m_tessControlShaderModule;
163 	vk::Move<vk::VkShaderModule>						m_tessEvaluationShaderModule;
164 	std::vector<vk::VkPipelineShaderStageCreateInfo>	m_shaderStages;
165 	std::vector<vk::VkVertexInputBindingDescription>	m_vertexInputBindings;
166 	std::vector<vk::VkVertexInputAttributeDescription>	m_vertexInputAttributes;
167 	vk::VkShaderStageFlags								m_shaderStageFlags;
168 	vk::VkCullModeFlags									m_cullModeFlags;
169 	vk::VkFrontFace										m_frontFace;
170 	deUint32											m_patchControlPoints;
171 	bool												m_blendEnable;
172 	vk::VkPrimitiveTopology								m_primitiveTopology;
173 
174 	GraphicsPipelineBuilder (const GraphicsPipelineBuilder&); // "deleted"
175 	GraphicsPipelineBuilder& operator= (const GraphicsPipelineBuilder&);
176 };
177 
178 // Base class that abstracts over legacy synchronization and synchronization changes
179 // introduced with VK_KHR_synchronization2 extension. Since structures in
180 // VK_KHR_synchronization2 have more features this wrapper uses them and when legacy
181 // implementation is used in tests then data from new structures is used to fill legacy ones.
182 class SynchronizationWrapperBase
183 {
184 public:
SynchronizationWrapperBase(const vk::DeviceInterface & vk)185 	SynchronizationWrapperBase(const vk::DeviceInterface& vk)
186 		: m_vk(vk)
187 	{}
188 
189 	virtual ~SynchronizationWrapperBase() = default;
190 
191 	virtual void			addSubmitInfo		(deUint32									waitSemaphoreInfoCount,
192 												 const vk::VkSemaphoreSubmitInfoKHR*		pWaitSemaphoreInfos,
193 												 deUint32									commandBufferInfoCount,
194 												 const vk::VkCommandBufferSubmitInfoKHR*	pCommandBufferInfos,
195 												 deUint32									signalSemaphoreInfoCount,
196 												 const vk::VkSemaphoreSubmitInfoKHR*		pSignalSemaphoreInfos,
197 												 bool										usingWaitTimelineSemaphore = DE_FALSE,
198 												 bool										usingSignalTimelineSemaphore = DE_FALSE) = 0;
199 
200 	virtual void			cmdPipelineBarrier	(vk::VkCommandBuffer						commandBuffer,
201 												 const vk::VkDependencyInfoKHR*				pDependencyInfo) const = 0;
202 
203 	virtual void			cmdSetEvent			(vk::VkCommandBuffer						commandBuffer,
204 												 vk::VkEvent								event,
205 												 const vk::VkDependencyInfoKHR*				pDependencyInfo) const = 0;
206 	virtual void			cmdResetEvent		(vk::VkCommandBuffer						commandBuffer,
207 												 vk::VkEvent								event,
208 												 vk::VkPipelineStageFlags2KHR				flag) const = 0;
209 	virtual void			cmdWaitEvents		(vk::VkCommandBuffer						commandBuffer,
210 												 deUint32									eventCount,
211 												 const vk::VkEvent*							pEvents,
212 												 const vk::VkDependencyInfoKHR*				pDependencyInfo) const = 0;
213 
214 	virtual vk::VkResult	queueSubmit			(vk::VkQueue								queue,
215 												 vk::VkFence								fence) = 0;
216 
217 protected:
218 	const vk::DeviceInterface& m_vk;
219 };
220 
221 enum FeatureFlagBits
222 {
223 	FEATURE_TESSELLATION_SHADER							= 1u << 0,
224 	FEATURE_GEOMETRY_SHADER								= 1u << 1,
225 	FEATURE_SHADER_FLOAT_64								= 1u << 2,
226 	FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS			= 1u << 3,
227 	FEATURE_FRAGMENT_STORES_AND_ATOMICS					= 1u << 4,
228 	FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE	= 1u << 5,
229 };
230 typedef deUint32 FeatureFlags;
231 
232 enum SyncPrimitive
233 {
234 	SYNC_PRIMITIVE_FENCE,
235 	SYNC_PRIMITIVE_BINARY_SEMAPHORE,
236 	SYNC_PRIMITIVE_TIMELINE_SEMAPHORE,
237 	SYNC_PRIMITIVE_BARRIER,
238 	SYNC_PRIMITIVE_EVENT,
239 };
240 
241 enum ResourceType
242 {
243 	RESOURCE_TYPE_BUFFER,
244 	RESOURCE_TYPE_IMAGE,
245 	RESOURCE_TYPE_INDIRECT_BUFFER_DRAW,
246 	RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED,
247 	RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH,
248 	RESOURCE_TYPE_INDEX_BUFFER,
249 };
250 
251 struct ResourceDescription
252 {
253 	ResourceType					type;
254 	tcu::IVec4						size;			//!< unused components are 0, e.g. for buffers only x is meaningful
255 	vk::VkImageType					imageType;
256 	vk::VkFormat					imageFormat;
257 	vk::VkImageAspectFlags			imageAspect;
258 	vk::VkSampleCountFlagBits		imageSamples;
259 };
260 
261 struct BufferResource
262 {
263 	vk::VkBuffer					handle;
264 	vk::VkDeviceSize				offset;
265 	vk::VkDeviceSize				size;
266 };
267 
268 struct ImageResource
269 {
270 	vk::VkImage						handle;
271 	vk::VkExtent3D					extent;
272 	vk::VkImageType					imageType;
273 	vk::VkFormat					format;
274 	vk::VkImageSubresourceRange		subresourceRange;
275 	vk::VkImageSubresourceLayers	subresourceLayers;
276 };
277 
278 typedef std::shared_ptr<SynchronizationWrapperBase> SynchronizationWrapperPtr;
279 SynchronizationWrapperPtr			getSynchronizationWrapper					(SynchronizationType				type,
280 																				 const vk::DeviceInterface&			vk,
281 																				 bool								usingTimelineSemaphores,
282 																				 deUint32							submitInfoCount = 1u);
283 void								submitCommandsAndWait						(SynchronizationWrapperPtr			synchronizationWrapper,
284 																				 const vk::DeviceInterface&			vk,
285 																				 const vk::VkDevice					device,
286 																				 const vk::VkQueue					queue,
287 																				 const vk::VkCommandBuffer			cmdBuffer);
288 vk::VkImageCreateInfo				makeImageCreateInfo							(const vk::VkImageType				imageType,
289 																				 const vk::VkExtent3D&				extent,
290 																				 const vk::VkFormat					format,
291 																				 const vk::VkImageUsageFlags		usage,
292 																				 const vk::VkSampleCountFlagBits	samples = vk::VK_SAMPLE_COUNT_1_BIT);
293 vk::Move<vk::VkCommandBuffer>		makeCommandBuffer							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool);
294 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);
295 void								beginRenderPassWithRasterizationDisabled	(const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer);
296 void								requireFeatures								(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const FeatureFlags flags);
297 void								requireStorageImageSupport					(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const vk::VkFormat fmt);
298 std::string							getResourceName								(const ResourceDescription& resource);
299 bool								isIndirectBuffer							(const ResourceType type);
300 vk::VkCommandBufferSubmitInfoKHR	makeCommonCommandBufferSubmitInfo			(const vk::VkCommandBuffer cmdBuf);
301 vk::VkSemaphoreSubmitInfoKHR		makeCommonSemaphoreSubmitInfo				(vk::VkSemaphore semaphore, deUint64 value, vk::VkPipelineStageFlags2KHR stageMask);
302 vk::VkDependencyInfoKHR				makeCommonDependencyInfo					(const vk::VkMemoryBarrier2KHR* pMemoryBarrier = DE_NULL, const vk::VkBufferMemoryBarrier2KHR* pBufferMemoryBarrier = DE_NULL, const vk::VkImageMemoryBarrier2KHR* pImageMemoryBarrier = DE_NULL);
303 
304 } // synchronization
305 } // vkt
306 
307 #endif // _VKTSYNCHRONIZATIONUTIL_HPP
308