1 #ifndef _VKTSYNCHRONIZATIONOPERATION_HPP 2 #define _VKTSYNCHRONIZATIONOPERATION_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 operation abstraction 24 *//*--------------------------------------------------------------------*/ 25 26 #include "tcuDefs.hpp" 27 #include "vkDefs.hpp" 28 #include "vkPrograms.hpp" 29 #include "vktTestCase.hpp" 30 #include "vktSynchronizationUtil.hpp" 31 #include "tcuVector.hpp" 32 #include "deUniquePtr.hpp" 33 #include "vkResourceInterface.hpp" 34 #include <string> 35 36 namespace vkt 37 { 38 namespace synchronization 39 { 40 41 enum OperationName 42 { 43 // Write operations 44 OPERATION_NAME_WRITE_FILL_BUFFER, 45 OPERATION_NAME_WRITE_UPDATE_BUFFER, 46 OPERATION_NAME_WRITE_COPY_BUFFER, 47 OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE, 48 OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER, 49 OPERATION_NAME_WRITE_COPY_IMAGE, 50 OPERATION_NAME_WRITE_BLIT_IMAGE, 51 OPERATION_NAME_WRITE_SSBO_VERTEX, 52 OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL, 53 OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION, 54 OPERATION_NAME_WRITE_SSBO_GEOMETRY, 55 OPERATION_NAME_WRITE_SSBO_FRAGMENT, 56 OPERATION_NAME_WRITE_SSBO_COMPUTE, 57 OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT, 58 OPERATION_NAME_WRITE_IMAGE_VERTEX, 59 OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL, 60 OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION, 61 OPERATION_NAME_WRITE_IMAGE_GEOMETRY, 62 OPERATION_NAME_WRITE_IMAGE_FRAGMENT, 63 OPERATION_NAME_WRITE_IMAGE_COMPUTE, 64 OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT, 65 OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE, 66 OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE, 67 OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE, 68 OPERATION_NAME_WRITE_DRAW, 69 OPERATION_NAME_WRITE_DRAW_INDEXED, 70 OPERATION_NAME_WRITE_DRAW_INDIRECT, 71 OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT, 72 OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS, 73 OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW, 74 OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED, 75 OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH, 76 OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER, 77 78 // Read operations 79 OPERATION_NAME_READ_COPY_BUFFER, 80 OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE, 81 OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER, 82 OPERATION_NAME_READ_COPY_IMAGE, 83 OPERATION_NAME_READ_BLIT_IMAGE, 84 OPERATION_NAME_READ_RESOLVE_IMAGE, 85 OPERATION_NAME_READ_UBO_VERTEX, 86 OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL, 87 OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION, 88 OPERATION_NAME_READ_UBO_GEOMETRY, 89 OPERATION_NAME_READ_UBO_FRAGMENT, 90 OPERATION_NAME_READ_UBO_COMPUTE, 91 OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT, 92 OPERATION_NAME_READ_UBO_TEXEL_VERTEX, 93 OPERATION_NAME_READ_UBO_TEXEL_TESSELLATION_CONTROL, 94 OPERATION_NAME_READ_UBO_TEXEL_TESSELLATION_EVALUATION, 95 OPERATION_NAME_READ_UBO_TEXEL_GEOMETRY, 96 OPERATION_NAME_READ_UBO_TEXEL_FRAGMENT, 97 OPERATION_NAME_READ_UBO_TEXEL_COMPUTE, 98 OPERATION_NAME_READ_UBO_TEXEL_COMPUTE_INDIRECT, 99 OPERATION_NAME_READ_SSBO_VERTEX, 100 OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL, 101 OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION, 102 OPERATION_NAME_READ_SSBO_GEOMETRY, 103 OPERATION_NAME_READ_SSBO_FRAGMENT, 104 OPERATION_NAME_READ_SSBO_COMPUTE, 105 OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT, 106 OPERATION_NAME_READ_IMAGE_VERTEX, 107 OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL, 108 OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION, 109 OPERATION_NAME_READ_IMAGE_GEOMETRY, 110 OPERATION_NAME_READ_IMAGE_FRAGMENT, 111 OPERATION_NAME_READ_IMAGE_COMPUTE, 112 OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT, 113 OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW, 114 OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED, 115 OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH, 116 OPERATION_NAME_READ_VERTEX_INPUT, 117 OPERATION_NAME_READ_INDEX_INPUT, 118 119 // Copy operations 120 OPERATION_NAME_COPY_BUFFER, 121 OPERATION_NAME_COPY_IMAGE, 122 OPERATION_NAME_BLIT_IMAGE, 123 OPERATION_NAME_COPY_SSBO_VERTEX, 124 OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL, 125 OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION, 126 OPERATION_NAME_COPY_SSBO_GEOMETRY, 127 OPERATION_NAME_COPY_SSBO_FRAGMENT, 128 OPERATION_NAME_COPY_SSBO_COMPUTE, 129 OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT, 130 OPERATION_NAME_COPY_IMAGE_VERTEX, 131 OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL, 132 OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION, 133 OPERATION_NAME_COPY_IMAGE_GEOMETRY, 134 OPERATION_NAME_COPY_IMAGE_FRAGMENT, 135 OPERATION_NAME_COPY_IMAGE_COMPUTE, 136 OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT, 137 }; 138 139 // Similar to Context, but allows test instance to decide which resources are used by the operation. 140 // E.g. this is needed when we want operation to work on a particular queue instead of the universal queue. 141 class OperationContext 142 { 143 public: 144 OperationContext(Context &context, SynchronizationType syncType, PipelineCacheData &pipelineCacheData); 145 146 OperationContext(Context &context, SynchronizationType syncType, const vk::DeviceInterface &vkd, 147 const vk::VkDevice device, vk::Allocator &allocator, PipelineCacheData &pipelineCacheData); 148 149 OperationContext(Context &context, SynchronizationType syncType, const vk::InstanceInterface &vki, 150 const vk::DeviceInterface &vkd, vk::VkPhysicalDevice physicalDevice, vk::VkDevice device, 151 vk::Allocator &allocator, vk::BinaryCollection &programCollection, 152 PipelineCacheData &pipelineCacheData); 153 getSynchronizationType(void) const154 SynchronizationType getSynchronizationType(void) const 155 { 156 return m_syncType; 157 } getInstanceInterface(void) const158 const vk::InstanceInterface &getInstanceInterface(void) const 159 { 160 return m_vki; 161 } getDeviceInterface(void) const162 const vk::DeviceInterface &getDeviceInterface(void) const 163 { 164 return m_vk; 165 } getPhysicalDevice(void) const166 vk::VkPhysicalDevice getPhysicalDevice(void) const 167 { 168 return m_physicalDevice; 169 } getDevice(void) const170 vk::VkDevice getDevice(void) const 171 { 172 return m_device; 173 } getAllocator(void) const174 vk::Allocator &getAllocator(void) const 175 { 176 return m_allocator; 177 } getBinaryCollection(void) const178 vk::BinaryCollection &getBinaryCollection(void) const 179 { 180 return m_progCollection; 181 } getPipelineCacheData(void) const182 PipelineCacheData &getPipelineCacheData(void) const 183 { 184 return m_pipelineCacheData; 185 } 186 isDeviceFunctionalitySupported(const std::string & extension) const187 bool isDeviceFunctionalitySupported(const std::string &extension) const 188 { 189 return m_context.isDeviceFunctionalitySupported(extension); 190 } 191 isComputeOnly(void)192 bool isComputeOnly(void) 193 { 194 return m_context.getTestContext().getCommandLine().isComputeOnly(); 195 } 196 getResourceInterface(void) const197 de::SharedPtr<vk::ResourceInterface> getResourceInterface(void) const 198 { 199 return m_context.getResourceInterface(); 200 } 201 202 private: 203 const vkt::Context &m_context; 204 const SynchronizationType m_syncType; 205 const vk::InstanceInterface &m_vki; 206 const vk::DeviceInterface &m_vk; 207 const vk::VkPhysicalDevice m_physicalDevice; 208 const vk::VkDevice m_device; 209 vk::Allocator &m_allocator; 210 vk::BinaryCollection &m_progCollection; 211 PipelineCacheData &m_pipelineCacheData; 212 213 // Disabled 214 OperationContext(const OperationContext &); 215 OperationContext &operator=(const OperationContext &); 216 }; 217 218 // Common interface to images and buffers used by operations. 219 class Resource 220 { 221 public: 222 Resource(OperationContext &context, const ResourceDescription &desc, const uint32_t usage, 223 const vk::VkSharingMode sharingMode = vk::VK_SHARING_MODE_EXCLUSIVE, 224 const std::vector<uint32_t> &queueFamilyIndex = std::vector<uint32_t>()); 225 226 Resource(ResourceType type, vk::Move<vk::VkBuffer> buffer, de::MovePtr<vk::Allocation> allocation, 227 vk::VkDeviceSize offset, vk::VkDeviceSize size); 228 229 Resource(vk::Move<vk::VkImage> image, de::MovePtr<vk::Allocation> allocation, const vk::VkExtent3D &extent, 230 vk::VkImageType imageType, vk::VkFormat format, vk::VkImageSubresourceRange subresourceRange, 231 vk::VkImageSubresourceLayers subresourceLayers, vk::VkImageTiling tiling); 232 getType(void) const233 ResourceType getType(void) const 234 { 235 return m_type; 236 } getBuffer(void) const237 const BufferResource &getBuffer(void) const 238 { 239 DE_ASSERT(m_bufferData.get()); 240 return *m_bufferData; 241 } getImage(void) const242 const ImageResource &getImage(void) const 243 { 244 DE_ASSERT(m_imageData.get()); 245 return *m_imageData; 246 } 247 248 vk::VkDeviceMemory getMemory(void) const; 249 250 private: 251 const ResourceType m_type; 252 de::MovePtr<Buffer> m_buffer; 253 de::MovePtr<BufferResource> m_bufferData; 254 de::MovePtr<Image> m_image; 255 de::MovePtr<ImageResource> m_imageData; 256 }; 257 258 // \note Meaning of image layout is different for read and write types of operations: 259 // read - the layout image must be in before being passed to the read operation 260 // write - the layout image will be in after the write operation has finished 261 struct SyncInfo 262 { 263 vk::VkPipelineStageFlags2KHR stageMask; // pipeline stage where read/write takes place 264 vk::VkAccessFlags2KHR accessMask; // type of access that is performed 265 vk::VkImageLayout imageLayout; // src (for reads) or dst (for writes) image layout 266 }; 267 268 struct Data 269 { 270 std::size_t size; 271 const uint8_t *data; 272 }; 273 274 // Abstract operation on a resource 275 // \note Meaning of getData is different for read and write operations: 276 // read - data actually read by the operation 277 // write - expected data that operation was supposed to write 278 // \note It's assumed that recordCommands is called only once (i.e. no multiple command buffers are using these commands). 279 class Operation 280 { 281 public: Operation(void)282 Operation(void) : m_specializedAccess(false) 283 { 284 } Operation(const bool specializedAccess)285 Operation(const bool specializedAccess) : m_specializedAccess(specializedAccess) 286 { 287 } ~Operation(void)288 virtual ~Operation(void) 289 { 290 } 291 292 virtual void recordCommands(const vk::VkCommandBuffer cmdBuffer) = 0; // commands that carry out this operation 293 virtual SyncInfo getInSyncInfo(void) const = 0; // data required to properly synchronize this operation 294 virtual SyncInfo getOutSyncInfo(void) const = 0; // data required to properly synchronize this operation 295 virtual Data getData(void) const = 0; // get raw data that was written to or read from actual resource 296 virtual void setData(const Data &data) = 0; // set raw data to be read from actual resource 297 298 private: 299 Operation(const Operation &); 300 Operation &operator=(const Operation &); 301 302 protected: 303 bool m_specializedAccess; 304 }; 305 306 // A helper class to init programs and create the operation when context becomes available. 307 // Throws OperationInvalidResourceError when resource and operation combination is not possible (e.g. buffer-specific op on an image). 308 class OperationSupport 309 { 310 public: OperationSupport(void)311 OperationSupport(void) : m_specializedAccess(false) 312 { 313 } OperationSupport(const bool specializedAccess)314 OperationSupport(const bool specializedAccess) : m_specializedAccess(specializedAccess) 315 { 316 } ~OperationSupport(void)317 virtual ~OperationSupport(void) 318 { 319 } 320 321 virtual uint32_t getInResourceUsageFlags(void) const = 0; 322 virtual uint32_t getOutResourceUsageFlags(void) const = 0; 323 virtual vk::VkQueueFlags getQueueFlags(const OperationContext &context) const = 0; initPrograms(vk::SourceCollections &) const324 virtual void initPrograms(vk::SourceCollections &) const 325 { 326 } //!< empty by default 327 328 virtual de::MovePtr<Operation> build(OperationContext &context, Resource &resource) const = 0; 329 virtual de::MovePtr<Operation> build(OperationContext &context, Resource &inResource, 330 Resource &outResource) const = 0; 331 getShaderStage(void)332 virtual vk::VkShaderStageFlagBits getShaderStage(void) 333 { 334 return vk::VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; 335 } 336 337 private: 338 OperationSupport(const OperationSupport &); 339 OperationSupport &operator=(const OperationSupport &); 340 341 protected: 342 bool m_specializedAccess; 343 }; 344 345 bool isResourceSupported(const OperationName opName, const ResourceDescription &resourceDesc); 346 bool isSpecializedAccessFlagSupported(const OperationName opName); 347 de::MovePtr<OperationSupport> makeOperationSupport(const OperationName opName, const ResourceDescription &resourceDesc, 348 const bool specializedAccess = false); 349 std::string getOperationName(const OperationName opName); 350 bool isStageSupported(const vk::VkShaderStageFlagBits stage, const vk::VkQueueFlags queueFlags); 351 352 } // namespace synchronization 353 } // namespace vkt 354 355 #endif // _VKTSYNCHRONIZATIONOPERATION_HPP 356