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