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