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