Merge vk-gl-cts/vulkan-cts-1.2.6 into vk-gl-cts/vulkan-cts-1.2.7
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / synchronization / vktSynchronizationOperation.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Synchronization operation abstraction
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationOperation.hpp"
25 #include "vkDefs.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "deUniquePtr.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include <vector>
42 #include <sstream>
43
44 namespace vkt
45 {
46 namespace synchronization
47 {
48 namespace
49 {
50 using namespace vk;
51
52 enum Constants
53 {
54         MAX_IMAGE_DIMENSION_2D  = 0x1000u,
55         MAX_UBO_RANGE                   = 0x4000u,
56         MAX_UPDATE_BUFFER_SIZE  = 0x10000u,
57 };
58
59 enum BufferType
60 {
61         BUFFER_TYPE_UNIFORM,
62         BUFFER_TYPE_STORAGE,
63 };
64
65 enum AccessMode
66 {
67         ACCESS_MODE_READ,
68         ACCESS_MODE_WRITE,
69 };
70
71 enum PipelineType
72 {
73         PIPELINE_TYPE_GRAPHICS,
74         PIPELINE_TYPE_COMPUTE,
75 };
76
77 static const char* const s_perVertexBlock =     "gl_PerVertex {\n"
78                                                                                         "    vec4 gl_Position;\n"
79                                                                                         "}";
80
81 static const SyncInfo emptySyncInfo =
82 {
83         0,                                                      // VkPipelineStageFlags         stageMask;
84         0,                                                      // VkAccessFlags                        accessMask;
85         VK_IMAGE_LAYOUT_UNDEFINED,      // VkImageLayout                        imageLayout;
86 };
87
88 std::string getShaderStageName(VkShaderStageFlagBits stage)
89 {
90         switch (stage)
91         {
92                 default:
93                         DE_FATAL("Unhandled stage!");
94                         return "";
95                 case VK_SHADER_STAGE_COMPUTE_BIT:
96                         return "compute";
97                 case VK_SHADER_STAGE_FRAGMENT_BIT:
98                         return "fragment";
99                 case VK_SHADER_STAGE_VERTEX_BIT:
100                         return "vertex";
101                 case VK_SHADER_STAGE_GEOMETRY_BIT:
102                         return "geometry";
103                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
104                         return "tess_control";
105                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
106                         return "tess_eval";
107         }
108 }
109
110 //! A pipeline that can be embedded inside an operation.
111 class Pipeline
112 {
113 public:
114         virtual                 ~Pipeline               (void) {}
115         virtual void    recordCommands  (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet) = 0;
116 };
117
118 //! Vertex data that covers the whole viewport with two triangles.
119 class VertexGrid
120 {
121 public:
122         VertexGrid (OperationContext& context)
123                 : m_vertexFormat (VK_FORMAT_R32G32B32A32_SFLOAT)
124                 , m_vertexStride (tcu::getPixelSize(mapVkFormat(m_vertexFormat)))
125         {
126                 const DeviceInterface&  vk                      = context.getDeviceInterface();
127                 const VkDevice                  device          = context.getDevice();
128                 Allocator&                              allocator       = context.getAllocator();
129
130                 // Vertex positions
131                 {
132                         m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
133                         m_vertexData.push_back(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
134                         m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
135
136                         m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
137                         m_vertexData.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
138                         m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
139                 }
140
141                 {
142                         const VkDeviceSize vertexDataSizeBytes = m_vertexData.size() * sizeof(m_vertexData[0]);
143
144                         m_vertexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
145                         DE_ASSERT(sizeof(m_vertexData[0]) == m_vertexStride);
146
147                         {
148                                 const Allocation& alloc = m_vertexBuffer->getAllocation();
149
150                                 deMemcpy(alloc.getHostPtr(), &m_vertexData[0], static_cast<std::size_t>(vertexDataSizeBytes));
151                                 flushAlloc(vk, device, alloc);
152                         }
153                 }
154
155                 // Indices
156                 {
157                         const VkDeviceSize      indexBufferSizeBytes    = sizeof(deUint32) * m_vertexData.size();
158                         const deUint32          numIndices                              = static_cast<deUint32>(m_vertexData.size());
159
160                         m_indexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(indexBufferSizeBytes, VK_BUFFER_USAGE_INDEX_BUFFER_BIT), MemoryRequirement::HostVisible));
161
162                         {
163                                 const Allocation&       alloc   = m_indexBuffer->getAllocation();
164                                 deUint32* const         pData   = static_cast<deUint32*>(alloc.getHostPtr());
165
166                                 for (deUint32 i = 0; i < numIndices; ++i)
167                                         pData[i] = i;
168
169                                 flushAlloc(vk, device, alloc);
170                         }
171                 }
172         }
173
174         VkFormat        getVertexFormat         (void) const { return m_vertexFormat; }
175         deUint32        getVertexStride         (void) const { return m_vertexStride; }
176         VkIndexType getIndexType                (void) const { return VK_INDEX_TYPE_UINT32; }
177         deUint32        getNumVertices          (void) const { return static_cast<deUint32>(m_vertexData.size()); }
178         deUint32        getNumIndices           (void) const { return getNumVertices(); }
179         VkBuffer        getVertexBuffer         (void) const { return **m_vertexBuffer; }
180         VkBuffer        getIndexBuffer          (void) const { return **m_indexBuffer; }
181
182 private:
183         const VkFormat                          m_vertexFormat;
184         const deUint32                          m_vertexStride;
185         std::vector<tcu::Vec4>          m_vertexData;
186         de::MovePtr<Buffer>                     m_vertexBuffer;
187         de::MovePtr<Buffer>                     m_indexBuffer;
188 };
189
190 //! Add flags for all shader stages required to support a particular stage (e.g. fragment requires vertex as well).
191 VkShaderStageFlags getRequiredStages (const VkShaderStageFlagBits stage)
192 {
193         VkShaderStageFlags flags = 0;
194
195         DE_ASSERT(stage == VK_SHADER_STAGE_COMPUTE_BIT || (stage & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
196
197         if (stage & VK_SHADER_STAGE_ALL_GRAPHICS)
198                 flags |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
199
200         if (stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
201                 flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
202
203         if (stage & VK_SHADER_STAGE_GEOMETRY_BIT)
204                 flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
205
206         if (stage & VK_SHADER_STAGE_COMPUTE_BIT)
207                 flags |= VK_SHADER_STAGE_COMPUTE_BIT;
208
209         return flags;
210 }
211
212 //! Check that SSBO read/write is available and that all shader stages are supported.
213 void requireFeaturesForSSBOAccess (OperationContext& context, const VkShaderStageFlags usedStages)
214 {
215         const InstanceInterface&        vki                     = context.getInstanceInterface();
216         const VkPhysicalDevice          physDevice      = context.getPhysicalDevice();
217         FeatureFlags                            flags           = (FeatureFlags)0;
218
219         if (usedStages & VK_SHADER_STAGE_FRAGMENT_BIT)
220                 flags |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
221
222         if (usedStages & (VK_SHADER_STAGE_ALL_GRAPHICS & (~VK_SHADER_STAGE_FRAGMENT_BIT)))
223                 flags |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
224
225         if (usedStages & VK_SHADER_STAGE_GEOMETRY_BIT)
226                 flags |= FEATURE_GEOMETRY_SHADER;
227
228         if (usedStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
229                 flags |= FEATURE_TESSELLATION_SHADER;
230
231         requireFeatures(vki, physDevice, flags);
232 }
233
234 Data getHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const VkDeviceSize size)
235 {
236         const DeviceInterface&  vk              = context.getDeviceInterface();
237         const VkDevice                  device  = context.getDevice();
238         const Allocation&               alloc   = hostBuffer.getAllocation();
239         const Data                              data    =
240         {
241                 static_cast<std::size_t>(size),                                 // std::size_t          size;
242                 static_cast<deUint8*>(alloc.getHostPtr()),              // const deUint8*       data;
243         };
244
245         invalidateAlloc(vk, device, alloc);
246
247         return data;
248 }
249
250 void setHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const Data& data)
251 {
252         const DeviceInterface&  vk              = context.getDeviceInterface();
253         const VkDevice                  device  = context.getDevice();
254         const Allocation&               alloc   = hostBuffer.getAllocation();
255
256         deMemcpy(alloc.getHostPtr(), data.data, data.size);
257         flushAlloc(vk, device, alloc);
258 }
259
260 void assertValidShaderStage (const VkShaderStageFlagBits stage)
261 {
262         switch (stage)
263         {
264                 case VK_SHADER_STAGE_VERTEX_BIT:
265                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
266                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
267                 case VK_SHADER_STAGE_GEOMETRY_BIT:
268                 case VK_SHADER_STAGE_FRAGMENT_BIT:
269                 case VK_SHADER_STAGE_COMPUTE_BIT:
270                         // OK
271                         break;
272
273                 default:
274                         DE_FATAL("Invalid shader stage");
275                         break;
276         }
277 }
278
279 VkPipelineStageFlags pipelineStageFlagsFromShaderStageFlagBits (const VkShaderStageFlagBits shaderStage)
280 {
281         switch (shaderStage)
282         {
283                 case VK_SHADER_STAGE_VERTEX_BIT:                                        return VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR;
284                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:          return VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR;
285                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:       return VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR;
286                 case VK_SHADER_STAGE_GEOMETRY_BIT:                                      return VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR;
287                 case VK_SHADER_STAGE_FRAGMENT_BIT:                                      return VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
288                 case VK_SHADER_STAGE_COMPUTE_BIT:                                       return VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR;
289
290                 // Other usages are probably an error, so flag that.
291                 default:
292                         DE_FATAL("Invalid shader stage");
293                         return (VkPipelineStageFlags)0;
294         }
295 }
296
297 //! Fill destination buffer with a repeating pattern.
298 void fillPattern (void* const pData, const VkDeviceSize size, bool useIndexPattern = false)
299 {
300         // There are two pattern options - most operations use primePattern,
301         // indexPattern is only needed for testing vertex index bufffer.
302         static const deUint8    primePattern[]  = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
303         static const deUint32   indexPattern[]  = { 0, 1, 2, 3, 4 };
304
305         const deUint8*                  pattern                 = (useIndexPattern ? reinterpret_cast<const deUint8*>(indexPattern)
306                                                                                                                            : primePattern);
307         const deUint32                  patternSize             = static_cast<deUint32>(useIndexPattern
308                                                                                                                            ? DE_LENGTH_OF_ARRAY(indexPattern)*sizeof(deUint32)
309                                                                                                                            : DE_LENGTH_OF_ARRAY(primePattern));
310         deUint8* const                  pBytes                  = static_cast<deUint8*>(pData);
311
312         for (deUint32 i = 0; i < size; ++i)
313                 pBytes[i] = pattern[i % patternSize];
314 }
315
316 //! Get size in bytes of a pixel buffer with given extent.
317 VkDeviceSize getPixelBufferSize (const VkFormat format, const VkExtent3D& extent)
318 {
319         const int pixelSize = tcu::getPixelSize(mapVkFormat(format));
320         return (pixelSize * extent.width * extent.height * extent.depth);
321 }
322
323 //! Determine the size of a 2D image that can hold sizeBytes data.
324 VkExtent3D get2DImageExtentWithSize (const VkDeviceSize sizeBytes, const deUint32 pixelSize)
325 {
326         const deUint32 size = static_cast<deUint32>(sizeBytes / pixelSize);
327
328         DE_ASSERT(size <= MAX_IMAGE_DIMENSION_2D * MAX_IMAGE_DIMENSION_2D);
329
330         return makeExtent3D(
331                 std::min(size, static_cast<deUint32>(MAX_IMAGE_DIMENSION_2D)),
332                 (size / MAX_IMAGE_DIMENSION_2D) + (size % MAX_IMAGE_DIMENSION_2D != 0 ? 1u : 0u),
333                 1u);
334 }
335
336 VkClearValue makeClearValue (const VkFormat format)
337 {
338         if (isDepthStencilFormat(format))
339                 return makeClearValueDepthStencil(0.4f, 21u);
340         else
341         {
342                 if (isIntFormat(format) || isUintFormat(format))
343                         return makeClearValueColorU32(8u, 16u, 24u, 32u);
344                 else
345                         return makeClearValueColorF32(0.25f, 0.49f, 0.75f, 1.0f);
346         }
347 }
348
349 void clearPixelBuffer (tcu::PixelBufferAccess& pixels, const VkClearValue& clearValue)
350 {
351         const tcu::TextureFormat                format                  = pixels.getFormat();
352         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
353
354         if (format.order == tcu::TextureFormat::D)
355         {
356                 for (int z = 0; z < pixels.getDepth(); z++)
357                 for (int y = 0; y < pixels.getHeight(); y++)
358                 for (int x = 0; x < pixels.getWidth(); x++)
359                         pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
360         }
361         else if (format.order == tcu::TextureFormat::S)
362         {
363                 for (int z = 0; z < pixels.getDepth(); z++)
364                 for (int y = 0; y < pixels.getHeight(); y++)
365                 for (int x = 0; x < pixels.getWidth(); x++)
366                         pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
367         }
368         else if (format.order == tcu::TextureFormat::DS)
369         {
370                 for (int z = 0; z < pixels.getDepth(); z++)
371                 for (int y = 0; y < pixels.getHeight(); y++)
372                 for (int x = 0; x < pixels.getWidth(); x++)
373                 {
374                         pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
375                         pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
376                 }
377         }
378         else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
379         {
380                 const tcu::UVec4 color (clearValue.color.uint32);
381
382                 for (int z = 0; z < pixels.getDepth(); z++)
383                 for (int y = 0; y < pixels.getHeight(); y++)
384                 for (int x = 0; x < pixels.getWidth(); x++)
385                         pixels.setPixel(color, x, y, z);
386         }
387         else
388         {
389                 const tcu::Vec4 color (clearValue.color.float32);
390
391                 for (int z = 0; z < pixels.getDepth(); z++)
392                 for (int y = 0; y < pixels.getHeight(); y++)
393                 for (int x = 0; x < pixels.getWidth(); x++)
394                         pixels.setPixel(color, x, y, z);
395         }
396 }
397
398 VkImageViewType getImageViewType (const VkImageType imageType)
399 {
400         switch (imageType)
401         {
402                 case VK_IMAGE_TYPE_1D:          return VK_IMAGE_VIEW_TYPE_1D;
403                 case VK_IMAGE_TYPE_2D:          return VK_IMAGE_VIEW_TYPE_2D;
404                 case VK_IMAGE_TYPE_3D:          return VK_IMAGE_VIEW_TYPE_3D;
405
406                 default:
407                         DE_FATAL("Unknown image type");
408                         return VK_IMAGE_VIEW_TYPE_LAST;
409         }
410 }
411
412 std::string getShaderImageType (const VkFormat format, const VkImageType imageType)
413 {
414         const tcu::TextureFormat        texFormat       = mapVkFormat(format);
415         const std::string                       formatPart      = tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
416                                                                                           tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
417         switch (imageType)
418         {
419                 case VK_IMAGE_TYPE_1D:  return formatPart + "image1D";
420                 case VK_IMAGE_TYPE_2D:  return formatPart + "image2D";
421                 case VK_IMAGE_TYPE_3D:  return formatPart + "image3D";
422
423                 default:
424                         DE_FATAL("Unknown image type");
425                         return "";
426         }
427 }
428
429 std::string getShaderImageFormatQualifier (const VkFormat format)
430 {
431         const tcu::TextureFormat        texFormat       = mapVkFormat(format);
432         const char*                                     orderPart       = DE_NULL;
433         const char*                                     typePart        = DE_NULL;
434
435         switch (texFormat.order)
436         {
437                 case tcu::TextureFormat::R:             orderPart = "r";        break;
438                 case tcu::TextureFormat::RG:    orderPart = "rg";       break;
439                 case tcu::TextureFormat::RGB:   orderPart = "rgb";      break;
440                 case tcu::TextureFormat::RGBA:  orderPart = "rgba";     break;
441
442                 default:
443                         DE_FATAL("Unksupported texture channel order");
444                         break;
445         }
446
447         switch (texFormat.type)
448         {
449                 case tcu::TextureFormat::FLOAT:                         typePart = "32f";               break;
450                 case tcu::TextureFormat::HALF_FLOAT:            typePart = "16f";               break;
451
452                 case tcu::TextureFormat::UNSIGNED_INT32:        typePart = "32ui";              break;
453                 case tcu::TextureFormat::UNSIGNED_INT16:        typePart = "16ui";              break;
454                 case tcu::TextureFormat::UNSIGNED_INT8:         typePart = "8ui";               break;
455
456                 case tcu::TextureFormat::SIGNED_INT32:          typePart = "32i";               break;
457                 case tcu::TextureFormat::SIGNED_INT16:          typePart = "16i";               break;
458                 case tcu::TextureFormat::SIGNED_INT8:           typePart = "8i";                break;
459
460                 case tcu::TextureFormat::UNORM_INT16:           typePart = "16";                break;
461                 case tcu::TextureFormat::UNORM_INT8:            typePart = "8";                 break;
462
463                 case tcu::TextureFormat::SNORM_INT16:           typePart = "16_snorm";  break;
464                 case tcu::TextureFormat::SNORM_INT8:            typePart = "8_snorm";   break;
465
466                 default:
467                         DE_FATAL("Unksupported texture channel type");
468                         break;
469         }
470
471         return std::string(orderPart) + typePart;
472 }
473
474 namespace FillUpdateBuffer
475 {
476
477 enum BufferOp
478 {
479         BUFFER_OP_FILL,
480         BUFFER_OP_UPDATE,
481         BUFFER_OP_UPDATE_WITH_INDEX_PATTERN,
482 };
483
484 class Implementation : public Operation
485 {
486 public:
487         Implementation (OperationContext& context, Resource& resource, const BufferOp bufferOp)
488                 : m_context             (context)
489                 , m_resource    (resource)
490                 , m_fillValue   (0x13)
491                 , m_bufferOp    (bufferOp)
492         {
493                 DE_ASSERT((m_resource.getBuffer().size % sizeof(deUint32)) == 0);
494                 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_resource.getBuffer().size <= MAX_UPDATE_BUFFER_SIZE);
495
496                 m_data.resize(static_cast<size_t>(m_resource.getBuffer().size));
497
498                 if (m_bufferOp == BUFFER_OP_FILL)
499                 {
500                         const std::size_t       size    = m_data.size() / sizeof(m_fillValue);
501                         deUint32* const         pData   = reinterpret_cast<deUint32*>(&m_data[0]);
502
503                         for (deUint32 i = 0; i < size; ++i)
504                                 pData[i] = m_fillValue;
505                 }
506                 else if (m_bufferOp == BUFFER_OP_UPDATE)
507                 {
508                         fillPattern(&m_data[0], m_data.size());
509                 }
510                 else if(m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN)
511                 {
512                         fillPattern(&m_data[0], m_data.size(), true);
513                 }
514         }
515
516         void recordCommands (const VkCommandBuffer cmdBuffer)
517         {
518                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
519
520                 if (m_bufferOp == BUFFER_OP_FILL)
521                 {
522                         vk.cmdFillBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_fillValue);
523
524                         SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
525                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
526                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                                   // VkPipelineStageFlags2KHR                     srcStageMask
527                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                             // VkAccessFlags2KHR                            srcAccessMask
528                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                                   // VkPipelineStageFlags2KHR                     dstStageMask
529                                 VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                                              // VkAccessFlags2KHR                            dstAccessMask
530                                 m_resource.getBuffer().handle,                                                  // VkBuffer                                                     buffer
531                                 0u,                                                                                                             // VkDeviceSize                                         offset
532                                 m_resource.getBuffer().size                                                             // VkDeviceSize                                         size
533                         );
534                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
535                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
536                 }
537                 else
538                         vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, reinterpret_cast<deUint32*>(&m_data[0]));
539         }
540
541         SyncInfo getInSyncInfo (void) const
542         {
543                 return emptySyncInfo;
544         }
545
546         SyncInfo getOutSyncInfo (void) const
547         {
548                 const SyncInfo syncInfo =
549                 {
550                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
551                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
552                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
553                 };
554
555                 return syncInfo;
556         }
557
558         Data getData (void) const
559         {
560                 const Data data =
561                 {
562                         m_data.size(),          // std::size_t          size;
563                         &m_data[0],                     // const deUint8*       data;
564                 };
565                 return data;
566         }
567
568         void setData (const Data& data)
569         {
570                 deMemcpy(&m_data[0], data.data, data.size);
571         }
572
573 private:
574         OperationContext&               m_context;
575         Resource&                               m_resource;
576         std::vector<deUint8>    m_data;
577         const deUint32                  m_fillValue;
578         const BufferOp                  m_bufferOp;
579 };
580
581 class Support : public OperationSupport
582 {
583 public:
584         Support (const ResourceDescription& resourceDesc, const BufferOp bufferOp)
585                 : m_resourceDesc        (resourceDesc)
586                 , m_bufferOp            (bufferOp)
587         {
588                 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_bufferOp == BUFFER_OP_UPDATE || m_bufferOp == BUFFER_OP_UPDATE_WITH_INDEX_PATTERN);
589                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
590         }
591
592         deUint32 getInResourceUsageFlags (void) const
593         {
594                 return 0;
595         }
596
597         deUint32 getOutResourceUsageFlags (void) const
598         {
599                 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
600         }
601
602         VkQueueFlags getQueueFlags (const OperationContext& context) const
603         {
604                 if (m_bufferOp == BUFFER_OP_FILL && !context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
605                 {
606                         return VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT;
607                 }
608
609                 return VK_QUEUE_TRANSFER_BIT;
610         }
611
612         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
613         {
614                 return de::MovePtr<Operation>(new Implementation(context, resource, m_bufferOp));
615         }
616
617         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
618         {
619                 DE_ASSERT(0);
620                 return de::MovePtr<Operation>();
621         }
622
623 private:
624         const ResourceDescription       m_resourceDesc;
625         const BufferOp                          m_bufferOp;
626 };
627
628 } // FillUpdateBuffer ns
629
630 namespace CopyBuffer
631 {
632
633 class Implementation : public Operation
634 {
635 public:
636         Implementation (OperationContext& context, Resource& resource, const AccessMode mode)
637                 : m_context             (context)
638                 , m_resource    (resource)
639                 , m_mode                (mode)
640         {
641                 const DeviceInterface&          vk                              = m_context.getDeviceInterface();
642                 const VkDevice                          device                  = m_context.getDevice();
643                 Allocator&                                      allocator               = m_context.getAllocator();
644                 const VkBufferUsageFlags        hostBufferUsage = (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
645
646                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, hostBufferUsage), MemoryRequirement::HostVisible));
647
648                 const Allocation& alloc = m_hostBuffer->getAllocation();
649
650                 if (m_mode == ACCESS_MODE_READ)
651                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
652                 else
653                         fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
654
655                 flushAlloc(vk, device, alloc);
656         }
657
658         void recordCommands (const VkCommandBuffer cmdBuffer)
659         {
660                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
661                 const VkBufferCopy                      copyRegion                              = makeBufferCopy(0u, 0u, m_resource.getBuffer().size);
662                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
663
664                 if (m_mode == ACCESS_MODE_READ)
665                 {
666                         vk.cmdCopyBuffer(cmdBuffer, m_resource.getBuffer().handle, **m_hostBuffer, 1u, &copyRegion);
667
668                         // Insert a barrier so copied data is available to the host
669                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
670                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                                   // VkPipelineStageFlags2KHR                     srcStageMask
671                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                             // VkAccessFlags2KHR                            srcAccessMask
672                                 VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                                               // VkPipelineStageFlags2KHR                     dstStageMask
673                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                                                  // VkAccessFlags2KHR                            dstAccessMask
674                                 **m_hostBuffer,                                                                                 // VkBuffer                                                     buffer
675                                 0u,                                                                                                             // VkDeviceSize                                         offset
676                                 m_resource.getBuffer().size                                                             // VkDeviceSize                                         size
677                         );
678                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
679                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
680                 }
681                 else
682                 {
683                         // Insert a barrier so buffer data is available to the device
684                         //const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
685                         //      VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                                               // VkPipelineStageFlags2KHR                     srcStageMask
686                         //      VK_ACCESS_2_HOST_WRITE_BIT_KHR,                                                 // VkAccessFlags2KHR                            srcAccessMask
687                         //      VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                                   // VkPipelineStageFlags2KHR                     dstStageMask
688                         //      VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                                              // VkAccessFlags2KHR                            dstAccessMask
689                         //      **m_hostBuffer,                                                                                 // VkBuffer                                                     buffer
690                         //      0u,                                                                                                             // VkDeviceSize                                         offset
691                         //      m_resource.getBuffer().size                                                             // VkDeviceSize                                         size
692                         //);
693                         //VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
694                         //synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
695
696                         vk.cmdCopyBuffer(cmdBuffer, **m_hostBuffer, m_resource.getBuffer().handle, 1u, &copyRegion);
697                 }
698         }
699
700         SyncInfo getInSyncInfo (void) const
701         {
702                 const VkAccessFlags access              = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : 0);
703                 const SyncInfo          syncInfo        =
704                 {
705                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
706                         access,                                                                 // VkAccessFlags                        accessMask;
707                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
708                 };
709                 return syncInfo;
710         }
711
712         SyncInfo getOutSyncInfo (void) const
713         {
714                 const VkAccessFlags access              = (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR : 0);
715                 const SyncInfo          syncInfo        =
716                 {
717                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
718                         access,                                                                 // VkAccessFlags                        accessMask;
719                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
720                 };
721                 return syncInfo;
722         }
723
724         Data getData (void) const
725         {
726                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
727         }
728
729         void setData (const Data& data)
730         {
731                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
732                 setHostBufferData(m_context, *m_hostBuffer, data);
733         }
734
735 private:
736         OperationContext&               m_context;
737         Resource&                               m_resource;
738         const AccessMode                m_mode;
739         de::MovePtr<Buffer>             m_hostBuffer;
740 };
741
742 class Support : public OperationSupport
743 {
744 public:
745         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
746                 : m_mode                        (mode)
747         {
748                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
749                 DE_UNREF(resourceDesc);
750         }
751
752         deUint32 getInResourceUsageFlags (void) const
753         {
754                 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
755         }
756
757         deUint32 getOutResourceUsageFlags (void) const
758         {
759                 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
760         }
761
762         VkQueueFlags getQueueFlags (const OperationContext& context) const
763         {
764                 DE_UNREF(context);
765                 return VK_QUEUE_TRANSFER_BIT;
766         }
767
768         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
769         {
770                 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
771         }
772
773         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
774         {
775                 DE_ASSERT(0);
776                 return de::MovePtr<Operation>();
777         }
778
779 private:
780         const AccessMode        m_mode;
781 };
782
783 class CopyImplementation : public Operation
784 {
785 public:
786         CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
787                 : m_context             (context)
788                 , m_inResource  (inResource)
789                 , m_outResource (outResource)
790         {
791         }
792
793         void recordCommands (const VkCommandBuffer cmdBuffer)
794         {
795                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
796                 const VkBufferCopy              copyRegion      = makeBufferCopy(0u, 0u, m_inResource.getBuffer().size);
797
798                 vk.cmdCopyBuffer(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getBuffer().handle, 1u, &copyRegion);
799         }
800
801         SyncInfo getInSyncInfo (void) const
802         {
803                 const SyncInfo          syncInfo        =
804                 {
805                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
806                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
807                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
808                 };
809                 return syncInfo;
810         }
811
812         SyncInfo getOutSyncInfo (void) const
813         {
814                 const SyncInfo          syncInfo        =
815                 {
816                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
817                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
818                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
819                 };
820                 return syncInfo;
821         }
822
823         Data getData (void) const
824         {
825                 Data data = { 0, DE_NULL };
826                 return data;
827         }
828
829         void setData (const Data&)
830         {
831                 DE_ASSERT(0);
832         }
833
834 private:
835         OperationContext&               m_context;
836         Resource&                               m_inResource;
837         Resource&                               m_outResource;
838         de::MovePtr<Buffer>             m_hostBuffer;
839 };
840
841 class CopySupport : public OperationSupport
842 {
843 public:
844         CopySupport (const ResourceDescription& resourceDesc)
845         {
846                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
847                 DE_UNREF(resourceDesc);
848         }
849
850         deUint32 getInResourceUsageFlags (void) const
851         {
852                 return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
853         }
854
855         deUint32 getOutResourceUsageFlags (void) const
856         {
857                 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
858         }
859
860         VkQueueFlags getQueueFlags (const OperationContext& context) const
861         {
862                 DE_UNREF(context);
863                 return VK_QUEUE_TRANSFER_BIT;
864         }
865
866         de::MovePtr<Operation> build (OperationContext&, Resource&) const
867         {
868                 DE_ASSERT(0);
869                 return de::MovePtr<Operation>();
870         }
871
872         de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
873         {
874                 return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
875         }
876 };
877
878 } // CopyBuffer ns
879
880 namespace CopyBlitResolveImage
881 {
882
883 class ImplementationBase : public Operation
884 {
885 public:
886         //! Copy/Blit/Resolve etc. operation
887         virtual void recordCopyCommand (const VkCommandBuffer cmdBuffer) = 0;
888
889         //! Get source stage mask that is used during read - added to test synchronization2 new stage masks
890         virtual VkPipelineStageFlags2KHR getReadSrcStageMask() const = 0;
891
892         ImplementationBase (OperationContext& context, Resource& resource, const AccessMode mode)
893                 : m_context             (context)
894                 , m_resource    (resource)
895                 , m_mode                (mode)
896                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
897         {
898                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
899                 const VkDevice                  device          = m_context.getDevice();
900                 Allocator&                              allocator       = m_context.getAllocator();
901
902                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
903                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
904                         MemoryRequirement::HostVisible));
905
906                 const Allocation& alloc = m_hostBuffer->getAllocation();
907                 if (m_mode == ACCESS_MODE_READ)
908                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
909                 else
910                         fillPattern(alloc.getHostPtr(), m_bufferSize);
911                 flushAlloc(vk, device, alloc);
912
913                 // Staging image
914                 const auto& imgResource = m_resource.getImage();
915                 m_image = de::MovePtr<Image>(new Image(
916                         vk, device, allocator,
917                         makeImageCreateInfo(imgResource.imageType, imgResource.extent, imgResource.format,
918                                                                 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
919                         MemoryRequirement::Any));
920         }
921
922         void recordCommands (const VkCommandBuffer cmdBuffer)
923         {
924                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
925                 const VkBufferImageCopy         bufferCopyRegion                = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
926                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
927
928                 // Staging image layout
929                 {
930                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
931                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
932                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
933                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
934                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
935                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
936                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
937                                 **m_image,                                                                              // VkImage                                                      image
938                                 m_resource.getImage().subresourceRange                  // VkImageSubresourceRange                      subresourceRange
939                         );
940                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
941                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
942                 }
943
944                 if (m_mode == ACCESS_MODE_READ)
945                 {
946                         // Resource Image -> Staging image
947                         recordCopyCommand(cmdBuffer);
948
949                         // Staging image layout
950                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
951                                 getReadSrcStageMask(),                                                  // VkPipelineStageFlags2KHR                     srcStageMask
952                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            srcAccessMask
953                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
954                                 VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                              // VkAccessFlags2KHR                            dstAccessMask
955                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        oldLayout
956                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                                        newLayout
957                                 **m_image,                                                                              // VkImage                                                      image
958                                 m_resource.getImage().subresourceRange                  // VkImageSubresourceRange                      subresourceRange
959                         );
960                         VkDependencyInfoKHR imageDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
961                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &imageDependencyInfo);
962
963                         // Image -> Host buffer
964                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
965
966                         // Insert a barrier so copied data is available to the host
967                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
968                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     srcStageMask
969                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            srcAccessMask
970                                 VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                               // VkPipelineStageFlags2KHR                     dstStageMask
971                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                                  // VkAccessFlags2KHR                            dstAccessMask
972                                 **m_hostBuffer,                                                                 // VkBuffer                                                     buffer
973                                 0u,                                                                                             // VkDeviceSize                                         offset
974                                 m_bufferSize                                                                    // VkDeviceSize                                         size
975                         );
976                         VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
977                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
978                 }
979                 else
980                 {
981                         // Host buffer -> Staging image
982                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
983
984                         // Staging image layout
985                         {
986                                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
987                                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     srcStageMask
988                                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            srcAccessMask
989                                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
990                                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                              // VkAccessFlags2KHR                            dstAccessMask
991                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        oldLayout
992                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                                        newLayout
993                                         **m_image,                                                                              // VkImage                                                      image
994                                         m_resource.getImage().subresourceRange                  // VkImageSubresourceRange                      subresourceRange
995                                 );
996                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
997                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
998                         }
999
1000                         // Resource image layout
1001                         {
1002                                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1003                                         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
1004                                         (VkAccessFlags2KHR)0,                                                   // VkAccessFlags2KHR                            srcAccessMask
1005                                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
1006                                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
1007                                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
1008                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
1009                                         m_resource.getImage().handle,                                   // VkImage                                                      image
1010                                         m_resource.getImage().subresourceRange                  // VkImageSubresourceRange                      subresourceRange
1011                                 );
1012                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1013                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1014                         }
1015
1016                         // Staging image -> Resource Image
1017                         recordCopyCommand(cmdBuffer);
1018                 }
1019         }
1020
1021         SyncInfo getInSyncInfo (void) const
1022         {
1023                 const VkAccessFlags2KHR access          = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1024                 const VkImageLayout             layout          = (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1025                 const SyncInfo                  syncInfo        =
1026                 {
1027                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
1028                         access,                                                                 // VkAccessFlags                        accessMask;
1029                         layout,                                                                 // VkImageLayout                        imageLayout;
1030                 };
1031                 return syncInfo;
1032         }
1033
1034         SyncInfo getOutSyncInfo (void) const
1035         {
1036                 const VkAccessFlags2KHR access          = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_TRANSFER_READ_BIT_KHR : VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
1037                 const VkImageLayout             layout          = (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
1038                 const SyncInfo                  syncInfo        =
1039                 {
1040                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
1041                         access,                                                                 // VkAccessFlags                        accessMask;
1042                         layout,                                                                 // VkImageLayout                        imageLayout;
1043                 };
1044                 return syncInfo;
1045         }
1046
1047         Data getData (void) const
1048         {
1049                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
1050         }
1051
1052         void setData (const Data& data)
1053         {
1054                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1055                 setHostBufferData(m_context, *m_hostBuffer, data);
1056         }
1057
1058 protected:
1059         OperationContext&               m_context;
1060         Resource&                               m_resource;
1061         const AccessMode                m_mode;
1062         const VkDeviceSize              m_bufferSize;
1063         de::MovePtr<Buffer>             m_hostBuffer;
1064         de::MovePtr<Image>              m_image;
1065 };
1066
1067 VkOffset3D makeExtentOffset (const Resource& resource)
1068 {
1069         DE_ASSERT(resource.getType() == RESOURCE_TYPE_IMAGE);
1070         const VkExtent3D extent = resource.getImage().extent;
1071
1072         switch (resource.getImage().imageType)
1073         {
1074                 case VK_IMAGE_TYPE_1D:  return makeOffset3D(extent.width, 1, 1);
1075                 case VK_IMAGE_TYPE_2D:  return makeOffset3D(extent.width, extent.height, 1);
1076                 case VK_IMAGE_TYPE_3D:  return makeOffset3D(extent.width, extent.height, extent.depth);
1077                 default:
1078                         DE_ASSERT(0);
1079                         return VkOffset3D();
1080         }
1081 }
1082
1083 VkImageBlit makeBlitRegion (const Resource& resource)
1084 {
1085         const VkImageBlit blitRegion =
1086         {
1087                 resource.getImage().subresourceLayers,                                  // VkImageSubresourceLayers    srcSubresource;
1088                 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) },  // VkOffset3D                  srcOffsets[2];
1089                 resource.getImage().subresourceLayers,                                  // VkImageSubresourceLayers    dstSubresource;
1090                 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) },  // VkOffset3D                  dstOffsets[2];
1091         };
1092         return blitRegion;
1093 }
1094
1095 class BlitImplementation : public ImplementationBase
1096 {
1097 public:
1098         BlitImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1099                 : ImplementationBase    (context, resource, mode)
1100                 , m_blitRegion                  (makeBlitRegion(m_resource))
1101         {
1102                 const InstanceInterface&        vki                             = m_context.getInstanceInterface();
1103                 const VkPhysicalDevice          physDevice              = m_context.getPhysicalDevice();
1104                 const auto&                                     imgResource             = m_resource.getImage();
1105                 const VkFormatProperties        formatProps             = getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1106                 const auto&                                     features                = ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1107                 const VkFormatFeatureFlags      requiredFlags   = (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1108
1109                 // SRC and DST blit is required because both images are using the same format.
1110                 if ((features & requiredFlags) != requiredFlags)
1111                         TCU_THROW(NotSupportedError, "Format doesn't support blits");
1112         }
1113
1114         void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1115         {
1116                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
1117
1118                 if (m_mode == ACCESS_MODE_READ)
1119                 {
1120                         // Resource Image -> Staging image
1121                         vk.cmdBlitImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1122                                 1u, &m_blitRegion, VK_FILTER_NEAREST);
1123                 }
1124                 else
1125                 {
1126                         // Staging image -> Resource Image
1127                         vk.cmdBlitImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1128                                 1u, &m_blitRegion, VK_FILTER_NEAREST);
1129                 }
1130         }
1131
1132         VkPipelineStageFlags2KHR getReadSrcStageMask() const
1133         {
1134                 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_BLIT_BIT_KHR;
1135         }
1136
1137
1138 private:
1139         const VkImageBlit       m_blitRegion;
1140 };
1141
1142 template <typename ImageCopyOrResolve>
1143 ImageCopyOrResolve makeImageRegion (const Resource& resource)
1144 {
1145         return
1146         {
1147                 resource.getImage().subresourceLayers,          // VkImageSubresourceLayers    srcSubresource;
1148                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  srcOffset;
1149                 resource.getImage().subresourceLayers,          // VkImageSubresourceLayers    dstSubresource;
1150                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  dstOffset;
1151                 resource.getImage().extent,                                     // VkExtent3D                  extent;
1152         };
1153 }
1154
1155 class CopyImplementation : public ImplementationBase
1156 {
1157 public:
1158         CopyImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
1159                 : ImplementationBase    (context, resource, mode)
1160                 , m_imageCopyRegion             (makeImageRegion<VkImageCopy>(m_resource))
1161         {
1162         }
1163
1164         void recordCopyCommand (const VkCommandBuffer cmdBuffer)
1165         {
1166                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
1167
1168                 if (m_mode == ACCESS_MODE_READ)
1169                 {
1170                         // Resource Image -> Staging image
1171                         vk.cmdCopyImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1172                 }
1173                 else
1174                 {
1175                         // Staging image -> Resource Image
1176                         vk.cmdCopyImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
1177                 }
1178         }
1179
1180         VkPipelineStageFlags2KHR getReadSrcStageMask() const
1181         {
1182                 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_COPY_BIT_KHR;
1183         }
1184
1185 private:
1186         const VkImageCopy       m_imageCopyRegion;
1187 };
1188
1189 class ResolveImplementation : public ImplementationBase
1190 {
1191 public:
1192         ResolveImplementation(OperationContext& context, Resource& resource, const AccessMode mode)
1193                 : ImplementationBase    (context, resource, mode)
1194                 , m_imageResolveRegion  (makeImageRegion<VkImageResolve>(resource))
1195         {
1196                 DE_ASSERT(m_mode == ACCESS_MODE_READ);
1197         }
1198
1199         void recordCopyCommand(const VkCommandBuffer cmdBuffer)
1200         {
1201                 const DeviceInterface&  vk = m_context.getDeviceInterface();
1202
1203                 // Resource Image -> Staging image
1204                 vk.cmdResolveImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageResolveRegion);
1205         }
1206
1207         VkPipelineStageFlags2KHR getReadSrcStageMask() const
1208         {
1209                 return (m_context.getSynchronizationType() == SynchronizationType::LEGACY) ? VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR : VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR;
1210         }
1211
1212 private:
1213         VkImageResolve m_imageResolveRegion;
1214 };
1215
1216 enum Type
1217 {
1218         TYPE_COPY,
1219         TYPE_BLIT,
1220         TYPE_RESOLVE,
1221 };
1222
1223 class Support : public OperationSupport
1224 {
1225 public:
1226         Support (const ResourceDescription& resourceDesc, const Type type, const AccessMode mode)
1227                 : m_type                                (type)
1228                 , m_mode                                (mode)
1229         {
1230                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1231
1232                 const bool isDepthStencil       = isDepthStencilFormat(resourceDesc.imageFormat);
1233                 m_requiredQueueFlags            = (isDepthStencil || m_type != TYPE_COPY ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1234
1235                 // Don't blit depth/stencil images.
1236                 DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1237         }
1238
1239         deUint32 getInResourceUsageFlags (void) const
1240         {
1241                 return (m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0);
1242         }
1243
1244         deUint32 getOutResourceUsageFlags (void) const
1245         {
1246                 return (m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0);
1247         }
1248
1249         VkQueueFlags getQueueFlags (const OperationContext& context) const
1250         {
1251                 DE_UNREF(context);
1252                 return m_requiredQueueFlags;
1253         }
1254
1255         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1256         {
1257                 if (m_type == TYPE_COPY)
1258                         return de::MovePtr<Operation>(new CopyImplementation(context, resource, m_mode));
1259                 else if (m_type == TYPE_BLIT)
1260                         return de::MovePtr<Operation>(new BlitImplementation(context, resource, m_mode));
1261                 else
1262                         return de::MovePtr<Operation>(new ResolveImplementation(context, resource, m_mode));
1263         }
1264
1265         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
1266         {
1267                 DE_ASSERT(0);
1268                 return de::MovePtr<Operation>();
1269         }
1270
1271 private:
1272         const Type                      m_type;
1273         const AccessMode        m_mode;
1274         VkQueueFlags            m_requiredQueueFlags;
1275 };
1276
1277 class BlitCopyImplementation : public Operation
1278 {
1279 public:
1280         BlitCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1281                 : m_context                     (context)
1282                 , m_inResource          (inResource)
1283                 , m_outResource         (outResource)
1284                 , m_blitRegion          (makeBlitRegion(m_inResource))
1285         {
1286                 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1287                 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1288
1289                 const InstanceInterface&        vki                             = m_context.getInstanceInterface();
1290                 const VkPhysicalDevice          physDevice              = m_context.getPhysicalDevice();
1291                 const auto&                                     imgResource             = m_inResource.getImage();
1292                 const VkFormatProperties        formatProps             = getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
1293                 const auto&                                     features                = ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
1294                 const VkFormatFeatureFlags      requiredFlags   = (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
1295
1296                 // SRC and DST blit is required because both images are using the same format.
1297                 if ((features & requiredFlags) != requiredFlags)
1298                         TCU_THROW(NotSupportedError, "Format doesn't support blits");
1299         }
1300
1301         void recordCommands (const VkCommandBuffer cmdBuffer)
1302         {
1303                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
1304                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1305
1306                 {
1307                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1308                                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                              // VkPipelineStageFlags2KHR                     srcStageMask
1309                                 (VkAccessFlags2KHR)0,                                                   // VkAccessFlags2KHR                            srcAccessMask
1310                                 VK_PIPELINE_STAGE_TRANSFER_BIT,                                 // VkPipelineStageFlags2KHR                     dstStageMask
1311                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
1312                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
1313                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
1314                                 m_outResource.getImage().handle,                                // VkImage                                                      image
1315                                 m_outResource.getImage().subresourceRange               // VkImageSubresourceRange                      subresourceRange
1316                         );
1317                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1318                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1319                 }
1320
1321                 vk.cmdBlitImage(cmdBuffer,
1322                                                 m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1323                                                 m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1324                                                 1u, &m_blitRegion, VK_FILTER_NEAREST);
1325         }
1326
1327         SyncInfo getInSyncInfo (void) const
1328         {
1329                 const SyncInfo          syncInfo        =
1330                 {
1331                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
1332                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
1333                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout                        imageLayout;
1334                 };
1335                 return syncInfo;
1336         }
1337
1338         SyncInfo getOutSyncInfo (void) const
1339         {
1340                 const SyncInfo          syncInfo        =
1341                 {
1342                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
1343                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
1344                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
1345                 };
1346                 return syncInfo;
1347         }
1348
1349         Data getData (void) const
1350         {
1351                 Data data = { 0, DE_NULL };
1352                 return data;
1353         }
1354
1355         void setData (const Data&)
1356         {
1357                 DE_ASSERT(0);
1358         }
1359
1360 private:
1361         OperationContext&       m_context;
1362         Resource&                       m_inResource;
1363         Resource&                       m_outResource;
1364         const VkImageBlit       m_blitRegion;
1365 };
1366
1367 class CopyCopyImplementation : public Operation
1368 {
1369 public:
1370         CopyCopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
1371                 : m_context                     (context)
1372                 , m_inResource          (inResource)
1373                 , m_outResource         (outResource)
1374                 , m_imageCopyRegion     (makeImageRegion<VkImageCopy>(m_inResource))
1375         {
1376                 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
1377                 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
1378         }
1379
1380         void recordCommands (const VkCommandBuffer cmdBuffer)
1381         {
1382                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
1383                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1384
1385                 {
1386                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1387                                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                              // VkPipelineStageFlags2KHR                     srcStageMask
1388                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
1389                                 VK_PIPELINE_STAGE_TRANSFER_BIT,                                 // VkPipelineStageFlags2KHR                     dstStageMask
1390                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
1391                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
1392                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
1393                                 m_outResource.getImage().handle,                                // VkImage                                                      image
1394                                 m_outResource.getImage().subresourceRange               // VkImageSubresourceRange                      subresourceRange
1395                         );
1396                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1397                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1398                 }
1399
1400                 vk.cmdCopyImage(cmdBuffer,
1401                                                 m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1402                                                 m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1403                                                 1u, &m_imageCopyRegion);
1404         }
1405
1406         SyncInfo getInSyncInfo (void) const
1407         {
1408                 const SyncInfo          syncInfo        =
1409                 {
1410                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
1411                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
1412                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout                        imageLayout;
1413                 };
1414                 return syncInfo;
1415         }
1416
1417         SyncInfo getOutSyncInfo (void) const
1418         {
1419                 const SyncInfo          syncInfo        =
1420                 {
1421                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
1422                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
1423                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
1424                 };
1425                 return syncInfo;
1426         }
1427
1428         Data getData (void) const
1429         {
1430                 Data data = { 0, DE_NULL };
1431                 return data;
1432         }
1433
1434         void setData (const Data&)
1435         {
1436                 DE_ASSERT(0);
1437         }
1438
1439 private:
1440         OperationContext&       m_context;
1441         Resource&                       m_inResource;
1442         Resource&                       m_outResource;
1443         const VkImageCopy       m_imageCopyRegion;
1444 };
1445
1446 class CopySupport : public OperationSupport
1447 {
1448 public:
1449         CopySupport (const ResourceDescription& resourceDesc, const Type type)
1450                 : m_type                                (type)
1451         {
1452                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
1453
1454                 const bool isDepthStencil       = isDepthStencilFormat(resourceDesc.imageFormat);
1455                 m_requiredQueueFlags            = (isDepthStencil || m_type == TYPE_BLIT ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
1456
1457                 // Don't blit depth/stencil images.
1458                 DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
1459         }
1460
1461         deUint32 getInResourceUsageFlags (void) const
1462         {
1463                 return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1464         }
1465
1466         deUint32 getOutResourceUsageFlags (void) const
1467         {
1468                 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1469         }
1470
1471         VkQueueFlags getQueueFlags (const OperationContext& context) const
1472         {
1473                 DE_UNREF(context);
1474                 return m_requiredQueueFlags;
1475         }
1476
1477         de::MovePtr<Operation> build (OperationContext&, Resource&) const
1478         {
1479                 DE_ASSERT(0);
1480                 return de::MovePtr<Operation>();
1481         }
1482
1483         de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
1484         {
1485                 if (m_type == TYPE_COPY)
1486                         return de::MovePtr<Operation>(new CopyCopyImplementation(context, inResource, outResource));
1487                 else
1488                         return de::MovePtr<Operation>(new BlitCopyImplementation(context, inResource, outResource));
1489         }
1490
1491 private:
1492         const Type                      m_type;
1493         VkQueueFlags            m_requiredQueueFlags;
1494 };
1495
1496 } // CopyBlitImage ns
1497
1498 namespace ShaderAccess
1499 {
1500
1501 enum DispatchCall
1502 {
1503         DISPATCH_CALL_DISPATCH,
1504         DISPATCH_CALL_DISPATCH_INDIRECT,
1505 };
1506
1507 class GraphicsPipeline : public Pipeline
1508 {
1509 public:
1510         GraphicsPipeline (OperationContext& context, const VkShaderStageFlagBits stage, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1511                 : m_vertices    (context)
1512         {
1513                 const DeviceInterface&          vk                              = context.getDeviceInterface();
1514                 const VkDevice                          device                  = context.getDevice();
1515                 Allocator&                                      allocator               = context.getAllocator();
1516                 const VkShaderStageFlags        requiredStages  = getRequiredStages(stage);
1517
1518                 // Color attachment
1519
1520                 m_colorFormat                                   = VK_FORMAT_R8G8B8A8_UNORM;
1521                 m_colorImageSubresourceRange    = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1522                 m_colorImageExtent                              = makeExtent3D(16u, 16u, 1u);
1523                 m_colorAttachmentImage                  = de::MovePtr<Image>(new Image(vk, device, allocator,
1524                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1525                                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1526                         MemoryRequirement::Any));
1527
1528                 // Pipeline
1529
1530                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
1531                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
1532                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
1533                 m_pipelineLayout                = makePipelineLayout(vk, device, descriptorSetLayout);
1534
1535                 GraphicsPipelineBuilder pipelineBuilder;
1536                 pipelineBuilder
1537                         .setRenderSize                                  (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
1538                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
1539                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
1540                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
1541
1542                 if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
1543                         pipelineBuilder
1544                                 .setPatchControlPoints  (m_vertices.getNumVertices())
1545                                 .setShader                              (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,          context.getBinaryCollection().get(shaderPrefix + "tesc"), DE_NULL)
1546                                 .setShader                              (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,       context.getBinaryCollection().get(shaderPrefix + "tese"), DE_NULL);
1547
1548                 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
1549                         pipelineBuilder
1550                                 .setShader      (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,      context.getBinaryCollection().get(shaderPrefix + "geom"), DE_NULL);
1551
1552                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
1553         }
1554
1555         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1556         {
1557                 const DeviceInterface&          vk                                              = context.getDeviceInterface();
1558                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
1559
1560                 // Change color attachment image layout
1561                 {
1562                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1563                                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                              // VkPipelineStageFlags2KHR                     srcStageMask
1564                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
1565                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags2KHR                     dstStageMask
1566                                 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,             // VkAccessFlags2KHR                            dstAccessMask
1567                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
1568                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                                        newLayout
1569                                 **m_colorAttachmentImage,                                               // VkImage                                                      image
1570                                 m_colorImageSubresourceRange                                    // VkImageSubresourceRange                      subresourceRange
1571                         );
1572                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1573                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1574                 }
1575
1576                 {
1577                         const VkRect2D  renderArea      = makeRect2D(m_colorImageExtent);
1578                         const tcu::Vec4 clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1579
1580                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
1581                 }
1582
1583                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1584                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1585                 {
1586                         const VkDeviceSize      vertexBufferOffset      = 0ull;
1587                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
1588                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1589                 }
1590
1591                 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
1592                 endRenderPass(vk, cmdBuffer);
1593         }
1594
1595 private:
1596         const VertexGrid                        m_vertices;
1597         VkFormat                                        m_colorFormat;
1598         de::MovePtr<Image>                      m_colorAttachmentImage;
1599         Move<VkImageView>                       m_colorAttachmentView;
1600         VkExtent3D                                      m_colorImageExtent;
1601         VkImageSubresourceRange         m_colorImageSubresourceRange;
1602         Move<VkRenderPass>                      m_renderPass;
1603         Move<VkFramebuffer>                     m_framebuffer;
1604         Move<VkPipelineLayout>          m_pipelineLayout;
1605         Move<VkPipeline>                        m_pipeline;
1606 };
1607
1608 class ComputePipeline : public Pipeline
1609 {
1610 public:
1611         ComputePipeline (OperationContext& context, const DispatchCall dispatchCall, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1612                 : m_dispatchCall        (dispatchCall)
1613         {
1614                 const DeviceInterface&  vk                      = context.getDeviceInterface();
1615                 const VkDevice                  device          = context.getDevice();
1616                 Allocator&                              allocator       = context.getAllocator();
1617
1618                 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1619                 {
1620                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
1621                                 makeBufferCreateInfo(sizeof(VkDispatchIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
1622
1623                         const Allocation&                                       alloc                           = m_indirectBuffer->getAllocation();
1624                         VkDispatchIndirectCommand* const        pIndirectCommand        = static_cast<VkDispatchIndirectCommand*>(alloc.getHostPtr());
1625
1626                         pIndirectCommand->x     = 1u;
1627                         pIndirectCommand->y = 1u;
1628                         pIndirectCommand->z     = 1u;
1629
1630                         flushAlloc(vk, device, alloc);
1631                 }
1632
1633                 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
1634
1635                 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
1636                 m_pipeline               = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData());
1637         }
1638
1639         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1640         {
1641                 const DeviceInterface&  vk      = context.getDeviceInterface();
1642
1643                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
1644                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1645
1646                 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1647                         vk.cmdDispatchIndirect(cmdBuffer, **m_indirectBuffer, 0u);
1648                 else
1649                         vk.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1650         }
1651
1652 private:
1653         const DispatchCall                      m_dispatchCall;
1654         de::MovePtr<Buffer>                     m_indirectBuffer;
1655         Move<VkPipelineLayout>          m_pipelineLayout;
1656         Move<VkPipeline>                        m_pipeline;
1657 };
1658
1659 //! Read/write operation on a UBO/SSBO in graphics/compute pipeline.
1660 class BufferImplementation : public Operation
1661 {
1662 public:
1663         BufferImplementation (OperationContext&                         context,
1664                                                   Resource&                                             resource,
1665                                                   const VkShaderStageFlagBits   stage,
1666                                                   const BufferType                              bufferType,
1667                                                   const std::string&                    shaderPrefix,
1668                                                   const AccessMode                              mode,
1669                                                   const PipelineType                    pipelineType,
1670                                                   const DispatchCall                    dispatchCall)
1671                 : m_context                     (context)
1672                 , m_resource            (resource)
1673                 , m_stage                       (stage)
1674                 , m_pipelineStage       (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1675                 , m_bufferType          (bufferType)
1676                 , m_mode                        (mode)
1677                 , m_dispatchCall        (dispatchCall)
1678         {
1679                 requireFeaturesForSSBOAccess (m_context, m_stage);
1680
1681                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1682                 const VkDevice                  device          = m_context.getDevice();
1683                 Allocator&                              allocator       = m_context.getAllocator();
1684
1685                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1686                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
1687
1688                 // Init host buffer data
1689                 {
1690                         const Allocation& alloc = m_hostBuffer->getAllocation();
1691                         if (m_mode == ACCESS_MODE_READ)
1692                                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
1693                         else
1694                                 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
1695                         flushAlloc(vk, device, alloc);
1696                 }
1697
1698                 // Prepare descriptors
1699                 {
1700                         const VkDescriptorType  bufferDescriptorType    = (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1701
1702                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1703                                 .addSingleBinding(bufferDescriptorType, m_stage)
1704                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
1705                                 .build(vk, device);
1706
1707                         m_descriptorPool = DescriptorPoolBuilder()
1708                                 .addType(bufferDescriptorType)
1709                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1710                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1711
1712                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1713
1714                         const VkDescriptorBufferInfo  bufferInfo         = makeDescriptorBufferInfo(m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size);
1715                         const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_resource.getBuffer().size);
1716
1717                         if (m_mode == ACCESS_MODE_READ)
1718                         {
1719                                 DescriptorSetUpdateBuilder()
1720                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescriptorType, &bufferInfo)
1721                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1722                                         .update(vk, device);
1723                         }
1724                         else
1725                         {
1726                                 DescriptorSetUpdateBuilder()
1727                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1728                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
1729                                         .update(vk, device);
1730                         }
1731                 }
1732
1733                 // Create pipeline
1734                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1735                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1736         }
1737
1738         void recordCommands (const VkCommandBuffer cmdBuffer)
1739         {
1740                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1741
1742                 // Post draw/dispatch commands
1743
1744                 if (m_mode == ACCESS_MODE_READ)
1745                 {
1746                         const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
1747                         SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1748
1749                         // Insert a barrier so data written by the shader is available to the host
1750                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
1751                                 m_pipelineStage,                                                        // VkPipelineStageFlags2KHR                     srcStageMask
1752                                 VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags2KHR                            srcAccessMask
1753                                 VK_PIPELINE_STAGE_HOST_BIT,                                     // VkPipelineStageFlags2KHR                     dstStageMask
1754                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                          // VkAccessFlags2KHR                            dstAccessMask
1755                                 **m_hostBuffer,                                                         // VkBuffer                                                     buffer
1756                                 0u,                                                                                     // VkDeviceSize                                         offset
1757                                 m_resource.getBuffer().size                                     // VkDeviceSize                                         size
1758                         );
1759                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
1760                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1761                 }
1762         }
1763
1764         SyncInfo getInSyncInfo (void) const
1765         {
1766                 const VkAccessFlags2KHR accessFlags = (m_mode == ACCESS_MODE_READ ? (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_ACCESS_2_UNIFORM_READ_BIT_KHR
1767                                                                                                                                                                                                                          : VK_ACCESS_2_SHADER_READ_BIT_KHR)
1768                                                                                                                                           : VK_ACCESS_2_SHADER_WRITE_BIT_KHR);
1769                 const SyncInfo                  syncInfo        =
1770                 {
1771                         m_pipelineStage,                                // VkPipelineStageFlags         stageMask;
1772                         accessFlags,                                    // VkAccessFlags                        accessMask;
1773                         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout                        imageLayout;
1774                 };
1775                 return syncInfo;
1776         }
1777
1778         SyncInfo getOutSyncInfo (void) const
1779         {
1780                 const VkAccessFlags     accessFlags = m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0;
1781                 const SyncInfo          syncInfo        =
1782                 {
1783                         m_pipelineStage,                                // VkPipelineStageFlags         stageMask;
1784                         accessFlags,                                    // VkAccessFlags                        accessMask;
1785                         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout                        imageLayout;
1786                 };
1787                 return syncInfo;
1788         }
1789
1790         Data getData (void) const
1791         {
1792                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
1793         }
1794
1795         void setData (const Data& data)
1796         {
1797                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
1798                 setHostBufferData(m_context, *m_hostBuffer, data);
1799         }
1800
1801 private:
1802         OperationContext&                       m_context;
1803         Resource&                                       m_resource;
1804         const VkShaderStageFlagBits     m_stage;
1805         const VkPipelineStageFlags      m_pipelineStage;
1806         const BufferType                        m_bufferType;
1807         const AccessMode                        m_mode;
1808         const DispatchCall                      m_dispatchCall;
1809         de::MovePtr<Buffer>                     m_hostBuffer;
1810         Move<VkDescriptorPool>          m_descriptorPool;
1811         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
1812         Move<VkDescriptorSet>           m_descriptorSet;
1813         de::MovePtr<Pipeline>           m_pipeline;
1814 };
1815
1816 class ImageImplementation : public Operation
1817 {
1818 public:
1819         ImageImplementation (OperationContext&                          context,
1820                                                  Resource&                                              resource,
1821                                                  const VkShaderStageFlagBits    stage,
1822                                                  const std::string&                             shaderPrefix,
1823                                                  const AccessMode                               mode,
1824                                                  const PipelineType                             pipelineType,
1825                                                  const DispatchCall                             dispatchCall)
1826                 : m_context                             (context)
1827                 , m_resource                    (resource)
1828                 , m_stage                               (stage)
1829                 , m_pipelineStage               (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1830                 , m_mode                                (mode)
1831                 , m_dispatchCall                (dispatchCall)
1832                 , m_hostBufferSizeBytes (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
1833         {
1834                 const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1835                 const InstanceInterface&        vki                     = m_context.getInstanceInterface();
1836                 const VkDevice                          device          = m_context.getDevice();
1837                 const VkPhysicalDevice          physDevice      = m_context.getPhysicalDevice();
1838                 Allocator&                                      allocator       = m_context.getAllocator();
1839
1840                 // Image stores are always required, in either access mode.
1841                 requireFeaturesForSSBOAccess(m_context, m_stage);
1842
1843                 // Some storage image formats may not be supported
1844                 const auto& imgResource = m_resource.getImage();
1845                 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
1846
1847                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1848                         vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1849                         MemoryRequirement::HostVisible));
1850
1851                 // Init host buffer data
1852                 {
1853                         const Allocation& alloc = m_hostBuffer->getAllocation();
1854                         if (m_mode == ACCESS_MODE_READ)
1855                                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
1856                         else
1857                                 fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
1858                         flushAlloc(vk, device, alloc);
1859                 }
1860
1861                 // Image resources
1862                 {
1863                         m_image = de::MovePtr<Image>(new Image(vk, device, allocator,
1864                                 makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format,
1865                                                                         (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
1866                                                                         VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
1867                                 MemoryRequirement::Any));
1868
1869                         if (m_mode == ACCESS_MODE_READ)
1870                         {
1871                                 m_srcImage = &m_resource.getImage().handle;
1872                                 m_dstImage = &(**m_image);
1873                         }
1874                         else
1875                         {
1876                                 m_srcImage = &(**m_image);
1877                                 m_dstImage = &m_resource.getImage().handle;
1878                         }
1879
1880                         const VkImageViewType viewType = getImageViewType(m_resource.getImage().imageType);
1881
1882                         m_srcImageView  = makeImageView(vk, device, *m_srcImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1883                         m_dstImageView  = makeImageView(vk, device, *m_dstImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1884                 }
1885
1886                 // Prepare descriptors
1887                 {
1888                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1889                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1890                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1891                                 .build(vk, device);
1892
1893                         m_descriptorPool = DescriptorPoolBuilder()
1894                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1895                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1896                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1897
1898                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1899
1900                         const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1901                         const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1902
1903                         DescriptorSetUpdateBuilder()
1904                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
1905                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
1906                                 .update(vk, device);
1907                 }
1908
1909                 // Create pipeline
1910                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1911                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1912         }
1913
1914         void recordCommands (const VkCommandBuffer cmdBuffer)
1915         {
1916                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
1917                 const VkBufferImageCopy         bufferCopyRegion                = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
1918                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
1919
1920                 // Destination image layout
1921                 {
1922                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1923                                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                      // VkPipelineStageFlags2KHR                     srcStageMask
1924                                 (VkAccessFlags)0,                                                       // VkAccessFlags2KHR                            srcAccessMask
1925                                 m_pipelineStage,                                                        // VkPipelineStageFlags2KHR                     dstStageMask
1926                                 VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags2KHR                            dstAccessMask
1927                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                        oldLayout
1928                                 VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                                        newLayout
1929                                 *m_dstImage,                                                            // VkImage                                                      image
1930                                 m_resource.getImage().subresourceRange          // VkImageSubresourceRange                      subresourceRange
1931                         );
1932                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1933                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1934                 }
1935
1936                 // In write mode, source image must be filled with data.
1937                 if (m_mode == ACCESS_MODE_WRITE)
1938                 {
1939                         // Layout for transfer
1940                         {
1941                                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1942                                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                      // VkPipelineStageFlags2KHR                     srcStageMask
1943                                         (VkAccessFlags)0,                                                       // VkAccessFlags2KHR                            srcAccessMask
1944                                         VK_PIPELINE_STAGE_TRANSFER_BIT,                         // VkPipelineStageFlags2KHR                     dstStageMask
1945                                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                     // VkAccessFlags2KHR                            dstAccessMask
1946                                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                        oldLayout
1947                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                                        newLayout
1948                                         *m_srcImage,                                                            // VkImage                                                      image
1949                                         m_resource.getImage().subresourceRange          // VkImageSubresourceRange                      subresourceRange
1950                                 );
1951                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1952                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1953                         }
1954
1955                         // Host buffer -> Src image
1956                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, *m_srcImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
1957
1958                         // Layout for shader reading
1959                         {
1960                                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1961                                         VK_PIPELINE_STAGE_TRANSFER_BIT,                         // VkPipelineStageFlags2KHR                     srcStageMask
1962                                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                     // VkAccessFlags2KHR                            srcAccessMask
1963                                         m_pipelineStage,                                                        // VkPipelineStageFlags2KHR                     dstStageMask
1964                                         VK_ACCESS_2_SHADER_READ_BIT_KHR,                        // VkAccessFlags2KHR                            dstAccessMask
1965                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                                        oldLayout
1966                                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                                        newLayout
1967                                         *m_srcImage,                                                            // VkImage                                                      image
1968                                         m_resource.getImage().subresourceRange          // VkImageSubresourceRange                      subresourceRange
1969                                 );
1970                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1971                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1972                         }
1973                 }
1974
1975                 // Execute shaders
1976
1977                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1978
1979                 // Post draw/dispatch commands
1980
1981                 if (m_mode == ACCESS_MODE_READ)
1982                 {
1983                         // Layout for transfer
1984                         {
1985                                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1986                                         m_pipelineStage,                                                        // VkPipelineStageFlags2KHR                     srcStageMask
1987                                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags2KHR                            srcAccessMask
1988                                         VK_PIPELINE_STAGE_TRANSFER_BIT,                         // VkPipelineStageFlags2KHR                     dstStageMask
1989                                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                      // VkAccessFlags2KHR                            dstAccessMask
1990                                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                                        oldLayout
1991                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                                        newLayout
1992                                         *m_dstImage,                                                            // VkImage                                                      image
1993                                         m_resource.getImage().subresourceRange          // VkImageSubresourceRange                      subresourceRange
1994                                 );
1995                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1996                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
1997                         }
1998
1999                         // Dst image -> Host buffer
2000                         vk.cmdCopyImageToBuffer(cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
2001
2002                         // Insert a barrier so data written by the shader is available to the host
2003                         {
2004                                 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
2005                                         VK_PIPELINE_STAGE_TRANSFER_BIT,                         // VkPipelineStageFlags2KHR                     srcStageMask
2006                                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                     // VkAccessFlags2KHR                            srcAccessMask
2007                                         VK_PIPELINE_STAGE_HOST_BIT,                                     // VkPipelineStageFlags2KHR                     dstStageMask
2008                                         VK_ACCESS_2_HOST_READ_BIT_KHR,                          // VkAccessFlags2KHR                            dstAccessMask
2009                                         **m_hostBuffer,                                                         // VkBuffer                                                     buffer
2010                                         0u,                                                                                     // VkDeviceSize                                         offset
2011                                         m_hostBufferSizeBytes                                           // VkDeviceSize                                         size
2012                                 );
2013                                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
2014                                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2015                         }
2016                 }
2017         }
2018
2019         SyncInfo getInSyncInfo (void) const
2020         {
2021                 const VkAccessFlags     accessFlags = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_2_SHADER_READ_BIT_KHR : 0);
2022                 const SyncInfo          syncInfo        =
2023                 {
2024                         m_pipelineStage,                        // VkPipelineStageFlags         stageMask;
2025                         accessFlags,                            // VkAccessFlags                        accessMask;
2026                         VK_IMAGE_LAYOUT_GENERAL,        // VkImageLayout                        imageLayout;
2027                 };
2028                 return syncInfo;
2029         }
2030
2031         SyncInfo getOutSyncInfo (void) const
2032         {
2033                 const VkAccessFlags     accessFlags = (m_mode == ACCESS_MODE_WRITE ? VK_ACCESS_2_SHADER_WRITE_BIT_KHR : 0);
2034                 const SyncInfo          syncInfo        =
2035                 {
2036                         m_pipelineStage,                        // VkPipelineStageFlags         stageMask;
2037                         accessFlags,                            // VkAccessFlags                        accessMask;
2038                         VK_IMAGE_LAYOUT_GENERAL,        // VkImageLayout                        imageLayout;
2039                 };
2040                 return syncInfo;
2041         }
2042
2043         Data getData (void) const
2044         {
2045                 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2046         }
2047
2048         void setData (const Data& data)
2049         {
2050                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE);
2051                 setHostBufferData(m_context, *m_hostBuffer, data);
2052         }
2053
2054 private:
2055         OperationContext&                       m_context;
2056         Resource&                                       m_resource;
2057         const VkShaderStageFlagBits     m_stage;
2058         const VkPipelineStageFlags      m_pipelineStage;
2059         const AccessMode                        m_mode;
2060         const DispatchCall                      m_dispatchCall;
2061         const VkDeviceSize                      m_hostBufferSizeBytes;
2062         de::MovePtr<Buffer>                     m_hostBuffer;
2063         de::MovePtr<Image>                      m_image;                        //! Additional image used as src or dst depending on operation mode.
2064         const VkImage*                          m_srcImage;
2065         const VkImage*                          m_dstImage;
2066         Move<VkImageView>                       m_srcImageView;
2067         Move<VkImageView>                       m_dstImageView;
2068         Move<VkDescriptorPool>          m_descriptorPool;
2069         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
2070         Move<VkDescriptorSet>           m_descriptorSet;
2071         de::MovePtr<Pipeline>           m_pipeline;
2072 };
2073
2074 //! Create generic passthrough shaders with bits of custom code inserted in a specific shader stage.
2075 void initPassthroughPrograms (SourceCollections&                        programCollection,
2076                                                           const std::string&                    shaderPrefix,
2077                                                           const std::string&                    declCode,
2078                                                           const std::string&                    mainCode,
2079                                                           const VkShaderStageFlagBits   stage)
2080 {
2081         const VkShaderStageFlags        requiredStages  = getRequiredStages(stage);
2082
2083         if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
2084         {
2085                 std::ostringstream src;
2086                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2087                         << "\n"
2088                         << "layout(location = 0) in vec4 v_in_position;\n"
2089                         << "\n"
2090                         << "out " << s_perVertexBlock << ";\n"
2091                         << "\n"
2092                         << (stage & VK_SHADER_STAGE_VERTEX_BIT ? declCode + "\n" : "")
2093                         << "void main (void)\n"
2094                         << "{\n"
2095                         << "    gl_Position = v_in_position;\n"
2096                         << (stage & VK_SHADER_STAGE_VERTEX_BIT ? mainCode : "")
2097                         << "}\n";
2098
2099                 if (!programCollection.glslSources.contains(shaderPrefix + "vert"))
2100                         programCollection.glslSources.add(shaderPrefix + "vert") << glu::VertexSource(src.str());
2101         }
2102
2103         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2104         {
2105                 std::ostringstream src;
2106                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2107                         << "\n"
2108                         << "layout(vertices = 3) out;\n"
2109                         << "\n"
2110                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2111                         << "\n"
2112                         << "out " << s_perVertexBlock << " gl_out[];\n"
2113                         << "\n"
2114                         << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? declCode + "\n" : "")
2115                         << "void main (void)\n"
2116                         << "{\n"
2117                         << "    gl_TessLevelInner[0] = 1.0;\n"
2118                         << "    gl_TessLevelInner[1] = 1.0;\n"
2119                         << "\n"
2120                         << "    gl_TessLevelOuter[0] = 1.0;\n"
2121                         << "    gl_TessLevelOuter[1] = 1.0;\n"
2122                         << "    gl_TessLevelOuter[2] = 1.0;\n"
2123                         << "    gl_TessLevelOuter[3] = 1.0;\n"
2124                         << "\n"
2125                         << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2126                         << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? "\n" + mainCode : "")
2127                         << "}\n";
2128
2129                 if (!programCollection.glslSources.contains(shaderPrefix + "tesc"))
2130                         programCollection.glslSources.add(shaderPrefix + "tesc") << glu::TessellationControlSource(src.str());
2131         }
2132
2133         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2134         {
2135                 std::ostringstream src;
2136                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2137                         << "\n"
2138                         << "layout(triangles, equal_spacing, ccw) in;\n"
2139                         << "\n"
2140                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
2141                         << "\n"
2142                         << "out " << s_perVertexBlock << ";\n"
2143                         << "\n"
2144                         << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? declCode + "\n" : "")
2145                         << "void main (void)\n"
2146                         << "{\n"
2147                         << "    vec3 px = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
2148                         << "    vec3 py = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
2149                         << "    vec3 pz = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
2150                         << "    gl_Position = vec4(px + py + pz, 1.0);\n"
2151                         << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? mainCode : "")
2152                         << "}\n";
2153
2154                 if (!programCollection.glslSources.contains(shaderPrefix + "tese"))
2155                         programCollection.glslSources.add(shaderPrefix + "tese") << glu::TessellationEvaluationSource(src.str());
2156         }
2157
2158         if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
2159         {
2160                 std::ostringstream src;
2161                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2162                         << "\n"
2163                         << "layout(triangles) in;\n"
2164                         << "layout(triangle_strip, max_vertices = 3) out;\n"
2165                         << "\n"
2166                         << "in " << s_perVertexBlock << " gl_in[];\n"
2167                         << "\n"
2168                         << "out " << s_perVertexBlock << ";\n"
2169                         << "\n"
2170                         << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? declCode + "\n" : "")
2171                         << "void main (void)\n"
2172                         << "{\n"
2173                         << "    gl_Position = gl_in[0].gl_Position;\n"
2174                         << "    EmitVertex();\n"
2175                         << "\n"
2176                         << "    gl_Position = gl_in[1].gl_Position;\n"
2177                         << "    EmitVertex();\n"
2178                         << "\n"
2179                         << "    gl_Position = gl_in[2].gl_Position;\n"
2180                         << "    EmitVertex();\n"
2181                         << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? "\n" + mainCode : "")
2182                         << "}\n";
2183
2184                 if (!programCollection.glslSources.contains(shaderPrefix + "geom"))
2185                         programCollection.glslSources.add(shaderPrefix + "geom") << glu::GeometrySource(src.str());
2186         }
2187
2188         if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
2189         {
2190                 std::ostringstream src;
2191                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2192                         << "\n"
2193                         << "layout(location = 0) out vec4 o_color;\n"
2194                         << "\n"
2195                         << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? declCode + "\n" : "")
2196                         << "void main (void)\n"
2197                         << "{\n"
2198                         << "    o_color = vec4(1.0);\n"
2199                         << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? "\n" + mainCode : "")
2200                         << "}\n";
2201
2202                 if (!programCollection.glslSources.contains(shaderPrefix + "frag"))
2203                         programCollection.glslSources.add(shaderPrefix + "frag") << glu::FragmentSource(src.str());
2204         }
2205
2206         if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
2207         {
2208                 std::ostringstream src;
2209                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2210                         << "\n"
2211                         << "layout(local_size_x = 1) in;\n"
2212                         << "\n"
2213                         << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? declCode + "\n" : "")
2214                         << "void main (void)\n"
2215                         << "{\n"
2216                         << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? mainCode : "")
2217                         << "}\n";
2218
2219                 if (!programCollection.glslSources.contains(shaderPrefix + "comp"))
2220                         programCollection.glslSources.add(shaderPrefix + "comp") << glu::ComputeSource(src.str());
2221         }
2222 }
2223
2224 class BufferSupport : public OperationSupport
2225 {
2226 public:
2227         BufferSupport (const ResourceDescription&       resourceDesc,
2228                                    const BufferType                             bufferType,
2229                                    const AccessMode                             mode,
2230                                    const VkShaderStageFlagBits  stage,
2231                                    const DispatchCall                   dispatchCall = DISPATCH_CALL_DISPATCH)
2232                 : m_resourceDesc        (resourceDesc)
2233                 , m_bufferType          (bufferType)
2234                 , m_mode                        (mode)
2235                 , m_stage                       (stage)
2236                 , m_shaderPrefix        (std::string(m_mode == ACCESS_MODE_READ ? "read_" : "write_") + (m_bufferType == BUFFER_TYPE_UNIFORM ? "ubo_" : "ssbo_"))
2237                 , m_dispatchCall        (dispatchCall)
2238         {
2239                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2240                 DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2241                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2242                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_bufferType == BUFFER_TYPE_STORAGE);
2243                 DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2244                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2245
2246                 assertValidShaderStage(m_stage);
2247         }
2248
2249         void initPrograms (SourceCollections& programCollection) const
2250         {
2251                 DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2252
2253                 const std::string       bufferTypeStr   = (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2254                 const int                       numVecElements  = static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4));  // std140 must be aligned to a multiple of 16
2255
2256                 std::ostringstream declSrc;
2257                 declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2258                                 << "    uvec4 data[" << numVecElements << "];\n"
2259                                 << "} b_in;\n"
2260                                 << "\n"
2261                                 << "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2262                                 << "    uvec4 data[" << numVecElements << "];\n"
2263                                 << "} b_out;\n";
2264
2265                 std::ostringstream copySrc;
2266                 copySrc << "    for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2267                                 << "        b_out.data[i] = b_in.data[i];\n"
2268                                 << "    }\n";
2269
2270                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2271         }
2272
2273         deUint32 getInResourceUsageFlags (void) const
2274         {
2275                 if (m_bufferType == BUFFER_TYPE_UNIFORM)
2276                         return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2277                 else
2278                         return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2279         }
2280
2281         deUint32 getOutResourceUsageFlags (void) const
2282         {
2283                 if (m_bufferType == BUFFER_TYPE_UNIFORM)
2284                         return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0;
2285                 else
2286                         return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0;
2287         }
2288
2289         VkQueueFlags getQueueFlags (const OperationContext& context) const
2290         {
2291                 DE_UNREF(context);
2292                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2293         }
2294
2295         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2296         {
2297                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2298                         return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2299                 else
2300                         return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2301         }
2302
2303         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2304         {
2305                 DE_ASSERT(0);
2306                 return de::MovePtr<Operation>();
2307         }
2308
2309 private:
2310         const ResourceDescription       m_resourceDesc;
2311         const BufferType                        m_bufferType;
2312         const AccessMode                        m_mode;
2313         const VkShaderStageFlagBits     m_stage;
2314         const std::string                       m_shaderPrefix;
2315         const DispatchCall                      m_dispatchCall;
2316 };
2317
2318 class ImageSupport : public OperationSupport
2319 {
2320 public:
2321         ImageSupport (const ResourceDescription&        resourceDesc,
2322                                   const AccessMode                              mode,
2323                                   const VkShaderStageFlagBits   stage,
2324                                   const DispatchCall                    dispatchCall = DISPATCH_CALL_DISPATCH)
2325                 : m_resourceDesc        (resourceDesc)
2326                 , m_mode                        (mode)
2327                 , m_stage                       (stage)
2328                 , m_shaderPrefix        (m_mode == ACCESS_MODE_READ ? "read_image_" : "write_image_")
2329                 , m_dispatchCall        (dispatchCall)
2330         {
2331                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2332                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2333                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2334
2335                 assertValidShaderStage(m_stage);
2336         }
2337
2338         void initPrograms (SourceCollections& programCollection) const
2339         {
2340                 const std::string       imageFormat     = getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2341                 const std::string       imageType       = getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2342
2343                 std::ostringstream declSrc;
2344                 declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly  uniform " << imageType << " srcImg;\n"
2345                                 << "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2346
2347                 std::ostringstream mainSrc;
2348                 if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2349                         mainSrc << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2350                                         << "        imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2351                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2352                         mainSrc << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2353                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2354                                         << "        imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2355                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2356                         mainSrc << "    for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2357                                         << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2358                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2359                                         << "        imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2360                 else
2361                         DE_ASSERT(0);
2362
2363                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2364         }
2365
2366         deUint32 getInResourceUsageFlags (void) const
2367         {
2368                 return VK_IMAGE_USAGE_STORAGE_BIT;
2369         }
2370
2371         deUint32 getOutResourceUsageFlags (void) const
2372         {
2373                 return VK_IMAGE_USAGE_STORAGE_BIT;
2374         }
2375
2376         VkQueueFlags getQueueFlags (const OperationContext& context) const
2377         {
2378                 DE_UNREF(context);
2379                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2380         }
2381
2382         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2383         {
2384                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2385                         return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2386                 else
2387                         return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2388         }
2389
2390         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
2391         {
2392                 DE_ASSERT(0);
2393                 return de::MovePtr<Operation>();
2394         }
2395
2396 private:
2397         const ResourceDescription       m_resourceDesc;
2398         const AccessMode                        m_mode;
2399         const VkShaderStageFlagBits     m_stage;
2400         const std::string                       m_shaderPrefix;
2401         const DispatchCall                      m_dispatchCall;
2402 };
2403
2404 //! Copy operation on a UBO/SSBO in graphics/compute pipeline.
2405 class BufferCopyImplementation : public Operation
2406 {
2407 public:
2408         BufferCopyImplementation (OperationContext&                             context,
2409                                                           Resource&                                             inResource,
2410                                                           Resource&                                             outResource,
2411                                                           const VkShaderStageFlagBits   stage,
2412                                                           const BufferType                              bufferType,
2413                                                           const std::string&                    shaderPrefix,
2414                                                           const PipelineType                    pipelineType,
2415                                                           const DispatchCall                    dispatchCall)
2416                 : m_context                     (context)
2417                 , m_inResource          (inResource)
2418                 , m_outResource         (outResource)
2419                 , m_stage                       (stage)
2420                 , m_pipelineStage       (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2421                 , m_bufferType          (bufferType)
2422                 , m_dispatchCall        (dispatchCall)
2423         {
2424                 requireFeaturesForSSBOAccess (m_context, m_stage);
2425
2426                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
2427                 const VkDevice                  device          = m_context.getDevice();
2428
2429                 // Prepare descriptors
2430                 {
2431                         const VkDescriptorType  bufferDescriptorType    = (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2432
2433                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2434                                 .addSingleBinding(bufferDescriptorType, m_stage)
2435                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
2436                                 .build(vk, device);
2437
2438                         m_descriptorPool = DescriptorPoolBuilder()
2439                                 .addType(bufferDescriptorType)
2440                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2441                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2442
2443                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2444
2445                         const VkDescriptorBufferInfo  inBufferInfo = makeDescriptorBufferInfo(m_inResource.getBuffer().handle, m_inResource.getBuffer().offset, m_inResource.getBuffer().size);
2446                         const VkDescriptorBufferInfo  outBufferInfo      = makeDescriptorBufferInfo(m_outResource.getBuffer().handle, m_outResource.getBuffer().offset, m_outResource.getBuffer().size);
2447
2448                         DescriptorSetUpdateBuilder()
2449                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inBufferInfo)
2450                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferInfo)
2451                                 .update(vk, device);
2452                 }
2453
2454                 // Create pipeline
2455                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2456                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2457         }
2458
2459         void recordCommands (const VkCommandBuffer cmdBuffer)
2460         {
2461                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2462         }
2463
2464         SyncInfo getInSyncInfo (void) const
2465         {
2466                 const SyncInfo          syncInfo        =
2467                 {
2468                         m_pipelineStage,                                        // VkPipelineStageFlags         stageMask;
2469                         VK_ACCESS_2_SHADER_READ_BIT_KHR,        // VkAccessFlags                        accessMask;
2470                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
2471                 };
2472                 return syncInfo;
2473         }
2474
2475         SyncInfo getOutSyncInfo (void) const
2476         {
2477                 const SyncInfo          syncInfo        =
2478                 {
2479                         m_pipelineStage,                                        // VkPipelineStageFlags         stageMask;
2480                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,       // VkAccessFlags                        accessMask;
2481                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
2482                 };
2483                 return syncInfo;
2484         }
2485
2486         Data getData (void) const
2487         {
2488                 Data data = { 0, DE_NULL };
2489                 return data;
2490         }
2491
2492         void setData (const Data&)
2493         {
2494                 DE_ASSERT(0);
2495         }
2496
2497 private:
2498         OperationContext&                       m_context;
2499         Resource&                                       m_inResource;
2500         Resource&                                       m_outResource;
2501         const VkShaderStageFlagBits     m_stage;
2502         const VkPipelineStageFlags      m_pipelineStage;
2503         const BufferType                        m_bufferType;
2504         const DispatchCall                      m_dispatchCall;
2505         Move<VkDescriptorPool>          m_descriptorPool;
2506         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
2507         Move<VkDescriptorSet>           m_descriptorSet;
2508         de::MovePtr<Pipeline>           m_pipeline;
2509 };
2510
2511 class CopyBufferSupport : public OperationSupport
2512 {
2513 public:
2514         CopyBufferSupport (const ResourceDescription&   resourceDesc,
2515                                            const BufferType                             bufferType,
2516                                            const VkShaderStageFlagBits  stage,
2517                                            const DispatchCall                   dispatchCall = DISPATCH_CALL_DISPATCH)
2518                 : m_resourceDesc        (resourceDesc)
2519                 , m_bufferType          (bufferType)
2520                 , m_stage                       (stage)
2521                 , m_shaderPrefix        (std::string("copy_") + getShaderStageName(stage) + (m_bufferType == BUFFER_TYPE_UNIFORM ? "_ubo_" : "_ssbo_"))
2522                 , m_dispatchCall        (dispatchCall)
2523         {
2524                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
2525                 DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
2526                 DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
2527                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2528
2529                 assertValidShaderStage(m_stage);
2530         }
2531
2532         void initPrograms (SourceCollections& programCollection) const
2533         {
2534                 DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
2535
2536                 const std::string       bufferTypeStr   = (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
2537                 const int                       numVecElements  = static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4));  // std140 must be aligned to a multiple of 16
2538
2539                 std::ostringstream declSrc;
2540                 declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
2541                                 << "    uvec4 data[" << numVecElements << "];\n"
2542                                 << "} b_in;\n"
2543                                 << "\n"
2544                                 << "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
2545                                 << "    uvec4 data[" << numVecElements << "];\n"
2546                                 << "} b_out;\n";
2547
2548                 std::ostringstream copySrc;
2549                 copySrc << "    for (int i = 0; i < " << numVecElements << "; ++i) {\n"
2550                                 << "        b_out.data[i] = b_in.data[i];\n"
2551                                 << "    }\n";
2552
2553                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
2554         }
2555
2556         deUint32 getInResourceUsageFlags (void) const
2557         {
2558                 return (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2559         }
2560
2561         deUint32 getOutResourceUsageFlags (void) const
2562         {
2563                 return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2564         }
2565
2566         VkQueueFlags getQueueFlags (const OperationContext& context) const
2567         {
2568                 DE_UNREF(context);
2569                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2570         }
2571
2572         de::MovePtr<Operation> build (OperationContext&, Resource&) const
2573         {
2574                 DE_ASSERT(0);
2575                 return de::MovePtr<Operation>();
2576         }
2577
2578         de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2579         {
2580                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2581                         return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2582                 else
2583                         return de::MovePtr<Operation>(new BufferCopyImplementation(context, inResource, outResource, m_stage, m_bufferType, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2584         }
2585
2586 private:
2587         const ResourceDescription       m_resourceDesc;
2588         const BufferType                        m_bufferType;
2589         const VkShaderStageFlagBits     m_stage;
2590         const std::string                       m_shaderPrefix;
2591         const DispatchCall                      m_dispatchCall;
2592 };
2593
2594 class CopyImageImplementation : public Operation
2595 {
2596 public:
2597         CopyImageImplementation (OperationContext&                              context,
2598                                                          Resource&                                              inResource,
2599                                                          Resource&                                              outResource,
2600                                                          const VkShaderStageFlagBits    stage,
2601                                                          const std::string&                             shaderPrefix,
2602                                                          const PipelineType                             pipelineType,
2603                                                          const DispatchCall                             dispatchCall)
2604                 : m_context                             (context)
2605                 , m_inResource                  (inResource)
2606                 , m_outResource                 (outResource)
2607                 , m_stage                               (stage)
2608                 , m_pipelineStage               (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2609                 , m_dispatchCall                (dispatchCall)
2610         {
2611                 const DeviceInterface&          vk                      = m_context.getDeviceInterface();
2612                 const InstanceInterface&        vki                     = m_context.getInstanceInterface();
2613                 const VkDevice                          device          = m_context.getDevice();
2614                 const VkPhysicalDevice          physDevice      = m_context.getPhysicalDevice();
2615
2616                 // Image stores are always required, in either access mode.
2617                 requireFeaturesForSSBOAccess(m_context, m_stage);
2618
2619                 // Some storage image formats may not be supported
2620                 const auto& imgResource = m_inResource.getImage();
2621                 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2622
2623                 // Image resources
2624                 {
2625                         const VkImageViewType viewType = getImageViewType(m_inResource.getImage().imageType);
2626
2627                         m_srcImageView  = makeImageView(vk, device, m_inResource.getImage().handle, viewType, m_inResource.getImage().format, m_inResource.getImage().subresourceRange);
2628                         m_dstImageView  = makeImageView(vk, device, m_outResource.getImage().handle, viewType, m_outResource.getImage().format, m_outResource.getImage().subresourceRange);
2629                 }
2630
2631                 // Prepare descriptors
2632                 {
2633                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2634                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2635                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
2636                                 .build(vk, device);
2637
2638                         m_descriptorPool = DescriptorPoolBuilder()
2639                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2640                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2641                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2642
2643                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2644
2645                         const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
2646                         const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
2647
2648                         DescriptorSetUpdateBuilder()
2649                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
2650                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
2651                                 .update(vk, device);
2652                 }
2653
2654                 // Create pipeline
2655                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
2656                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
2657         }
2658
2659         void recordCommands (const VkCommandBuffer cmdBuffer)
2660         {
2661                 {
2662                         const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
2663                         SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2664
2665                         const VkImageMemoryBarrier2KHR imageMemoryBarriers2 = makeImageMemoryBarrier2(
2666                                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                              // VkPipelineStageFlags2KHR                     srcStageMask
2667                                         (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
2668                                         m_pipelineStage,                                                                // VkPipelineStageFlags2KHR                     dstStageMask
2669                                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                               // VkAccessFlags2KHR                            dstAccessMask
2670                                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
2671                                         VK_IMAGE_LAYOUT_GENERAL,                                                // VkImageLayout                                        newLayout
2672                                         m_outResource.getImage().handle,                                // VkImage                                                      image
2673                                         m_outResource.getImage().subresourceRange               // VkImageSubresourceRange                      subresourceRange
2674                         );
2675                         VkDependencyInfoKHR dependencyInfo
2676                         {
2677                                 VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,                          // VkStructureType                                      sType
2678                                 DE_NULL,                                                                                        // const void*                                          pNext
2679                                 VK_DEPENDENCY_BY_REGION_BIT,                                            // VkDependencyFlags                            dependencyFlags
2680                                 0u,                                                                                                     // deUint32                                                     memoryBarrierCount
2681                                 DE_NULL,                                                                                        // const VkMemoryBarrier2KHR*           pMemoryBarriers
2682                                 0u,                                                                                                     // deUint32                                                     bufferMemoryBarrierCount
2683                                 DE_NULL,                                                                                        // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers
2684                                 1,                                                                                                      // deUint32                                                     imageMemoryBarrierCount
2685                                 &imageMemoryBarriers2                                                           // const VkImageMemoryBarrier2KHR*      pImageMemoryBarriers
2686                         };
2687                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2688                 }
2689
2690                 // Execute shaders
2691                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2692         }
2693
2694         SyncInfo getInSyncInfo (void) const
2695         {
2696                 const SyncInfo          syncInfo        =
2697                 {
2698                         m_pipelineStage,                                        // VkPipelineStageFlags         stageMask;
2699                         VK_ACCESS_2_SHADER_READ_BIT_KHR,        // VkAccessFlags                        accessMask;
2700                         VK_IMAGE_LAYOUT_GENERAL,                        // VkImageLayout                        imageLayout;
2701                 };
2702                 return syncInfo;
2703         }
2704
2705         SyncInfo getOutSyncInfo (void) const
2706         {
2707                 const SyncInfo          syncInfo        =
2708                 {
2709                         m_pipelineStage,                                        // VkPipelineStageFlags         stageMask;
2710                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,       // VkAccessFlags                        accessMask;
2711                         VK_IMAGE_LAYOUT_GENERAL,                        // VkImageLayout                        imageLayout;
2712                 };
2713                 return syncInfo;
2714         }
2715
2716         Data getData (void) const
2717         {
2718                 Data data = { 0, DE_NULL };
2719                 return data;
2720         }
2721
2722         void setData (const Data&)
2723         {
2724                 DE_ASSERT(0);
2725         }
2726
2727 private:
2728         OperationContext&                       m_context;
2729         Resource&                                       m_inResource;
2730         Resource&                                       m_outResource;
2731         const VkShaderStageFlagBits     m_stage;
2732         const VkPipelineStageFlags      m_pipelineStage;
2733         const DispatchCall                      m_dispatchCall;
2734         Move<VkImageView>                       m_srcImageView;
2735         Move<VkImageView>                       m_dstImageView;
2736         Move<VkDescriptorPool>          m_descriptorPool;
2737         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
2738         Move<VkDescriptorSet>           m_descriptorSet;
2739         de::MovePtr<Pipeline>           m_pipeline;
2740 };
2741
2742 class CopyImageSupport : public OperationSupport
2743 {
2744 public:
2745         CopyImageSupport (const ResourceDescription&    resourceDesc,
2746                                           const VkShaderStageFlagBits   stage,
2747                                           const DispatchCall                    dispatchCall = DISPATCH_CALL_DISPATCH)
2748                 : m_resourceDesc        (resourceDesc)
2749                 , m_stage                       (stage)
2750                 , m_shaderPrefix        (std::string("copy_image_") + getShaderStageName(stage) + "_")
2751                 , m_dispatchCall        (dispatchCall)
2752         {
2753                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2754                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
2755
2756                 assertValidShaderStage(m_stage);
2757         }
2758
2759         void initPrograms (SourceCollections& programCollection) const
2760         {
2761                 const std::string       imageFormat     = getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
2762                 const std::string       imageType       = getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
2763
2764                 std::ostringstream declSrc;
2765                 declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly  uniform " << imageType << " srcImg;\n"
2766                                 << "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
2767
2768                 std::ostringstream mainSrc;
2769                 if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
2770                         mainSrc << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2771                                         << "        imageStore(dstImg, x, imageLoad(srcImg, x));\n";
2772                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
2773                         mainSrc << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2774                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2775                                         << "        imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
2776                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
2777                         mainSrc << "    for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
2778                                         << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
2779                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
2780                                         << "        imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
2781                 else
2782                         DE_ASSERT(0);
2783
2784                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
2785         }
2786
2787         deUint32 getInResourceUsageFlags (void) const
2788         {
2789                 return VK_IMAGE_USAGE_STORAGE_BIT;
2790         }
2791
2792         deUint32 getOutResourceUsageFlags (void) const
2793         {
2794                 return VK_IMAGE_USAGE_STORAGE_BIT;
2795         }
2796
2797         VkQueueFlags getQueueFlags (const OperationContext& context) const
2798         {
2799                 DE_UNREF(context);
2800                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
2801         }
2802
2803         de::MovePtr<Operation> build (OperationContext&, Resource&) const
2804         {
2805                 DE_ASSERT(0);
2806                 return de::MovePtr<Operation>();
2807         }
2808
2809         de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
2810         {
2811                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
2812                         return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
2813                 else
2814                         return de::MovePtr<Operation>(new CopyImageImplementation(context, inResource, outResource, m_stage, m_shaderPrefix, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
2815         }
2816
2817 private:
2818         const ResourceDescription       m_resourceDesc;
2819         const VkShaderStageFlagBits     m_stage;
2820         const std::string                       m_shaderPrefix;
2821         const DispatchCall                      m_dispatchCall;
2822 };
2823
2824 class MSImageImplementation : public Operation
2825 {
2826 public:
2827         MSImageImplementation(OperationContext& context,
2828                                                   Resource&                     resource)
2829                 : m_context             (context)
2830                 , m_resource    (resource)
2831                 , m_hostBufferSizeBytes(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
2832         {
2833                 const DeviceInterface&                  vk                      = m_context.getDeviceInterface();
2834                 const InstanceInterface&                vki                     = m_context.getInstanceInterface();
2835                 const VkDevice                                  device          = m_context.getDevice();
2836                 const VkPhysicalDevice                  physDevice      = m_context.getPhysicalDevice();
2837                 const VkPhysicalDeviceFeatures  features        = getPhysicalDeviceFeatures(vki, physDevice);
2838                 Allocator&                                              allocator       = m_context.getAllocator();
2839
2840                 const auto& imgResource = m_resource.getImage();
2841                 requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
2842                 if (!features.shaderStorageImageMultisample)
2843                         TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
2844
2845                 VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2846                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2847                 const Allocation& alloc = m_hostBuffer->getAllocation();
2848                 fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
2849                 flushAlloc(vk, device, alloc);
2850
2851                 const ImageResource&  image             = m_resource.getImage();
2852                 const VkImageViewType viewType  = getImageViewType(image.imageType);
2853                 m_imageView = makeImageView(vk, device, image.handle, viewType, image.format, image.subresourceRange);
2854
2855                 // Prepare descriptors
2856                 {
2857                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2858                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2859                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  VK_SHADER_STAGE_COMPUTE_BIT)
2860                                 .build(vk, device);
2861
2862                         m_descriptorPool = DescriptorPoolBuilder()
2863                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2864                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
2865                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2866
2867                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2868
2869                         const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
2870                         const VkDescriptorImageInfo  imageInfo  = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
2871
2872                         DescriptorSetUpdateBuilder()
2873                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
2874                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  &imageInfo)
2875                                 .update(vk, device);
2876                 }
2877
2878                 // Create pipeline
2879                 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get("comp"), (VkShaderModuleCreateFlags)0));
2880                 m_pipelineLayout        = makePipelineLayout (vk, device, *m_descriptorSetLayout);
2881                 m_pipeline                      = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData());
2882         }
2883
2884         void recordCommands(const VkCommandBuffer cmdBuffer)
2885         {
2886                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
2887                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
2888
2889                 // change image layout
2890                 {
2891                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
2892                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,        // VkPipelineStageFlags2KHR                     srcStageMask
2893                                 (VkAccessFlags)0,                                                       // VkAccessFlags2KHR                            srcAccessMask
2894                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR,     // VkPipelineStageFlags2KHR                     dstStageMask
2895                                 VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags2KHR                            dstAccessMask
2896                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                        oldLayout
2897                                 VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                                        newLayout
2898                                 m_resource.getImage().handle,                           // VkImage                                                      image
2899                                 m_resource.getImage().subresourceRange          // VkImageSubresourceRange                      subresourceRange
2900                         );
2901                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
2902                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
2903                 }
2904
2905                 // execute shader
2906                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
2907                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
2908                 vk.cmdDispatch(cmdBuffer, m_resource.getImage().extent.width, m_resource.getImage().extent.height, 1u);
2909         }
2910
2911         SyncInfo getInSyncInfo(void) const
2912         {
2913                 DE_ASSERT(false);
2914                 return emptySyncInfo;
2915         }
2916
2917         SyncInfo getOutSyncInfo(void) const
2918         {
2919                 return
2920                 {
2921                         VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR,     // VkPipelineStageFlags         stageMask;
2922                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags                        accessMask;
2923                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        imageLayout;
2924                 };
2925         }
2926
2927         Data getData(void) const
2928         {
2929                 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2930         }
2931
2932         void setData(const Data&)
2933         {
2934                 DE_ASSERT(false);
2935         }
2936
2937 private:
2938         OperationContext&                       m_context;
2939         Resource&                                       m_resource;
2940         Move<VkImageView>                       m_imageView;
2941
2942         const VkDeviceSize                      m_hostBufferSizeBytes;
2943         de::MovePtr<Buffer>                     m_hostBuffer;
2944
2945         Move<VkDescriptorPool>          m_descriptorPool;
2946         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
2947         Move<VkDescriptorSet>           m_descriptorSet;
2948         Move<VkPipelineLayout>          m_pipelineLayout;
2949         Move<VkPipeline>                        m_pipeline;
2950 };
2951
2952 class MSImageSupport : public OperationSupport
2953 {
2954 public:
2955         MSImageSupport(const ResourceDescription& resourceDesc)
2956                 : m_resourceDesc        (resourceDesc)
2957         {
2958                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2959         }
2960
2961         void initPrograms (SourceCollections& programCollection) const
2962         {
2963                 std::stringstream source;
2964                 source <<
2965                         "#version 440\n"
2966                         "\n"
2967                         "layout(local_size_x = 1) in;\n"
2968                         "layout(set = 0, binding = 0, std430) readonly buffer Input {\n"
2969                         "    uint data[];\n"
2970                         "} inData;\n"
2971                         "layout(set = 0, binding = 1, r32ui) writeonly uniform uimage2DMS msImage;\n"
2972                         "\n"
2973                         "void main (void)\n"
2974                         "{\n"
2975                         "  int  gx    = int(gl_GlobalInvocationID.x);\n"
2976                         "  int  gy    = int(gl_GlobalInvocationID.y);\n"
2977                         "  uint value = inData.data[gy * " << m_resourceDesc.size.x() << " + gx];\n"
2978                         "  for (int sampleNdx = 0; sampleNdx < " << m_resourceDesc.imageSamples << "; ++sampleNdx)\n"
2979                         "    imageStore(msImage, ivec2(gx, gy), sampleNdx, uvec4(value));\n"
2980                         "}\n";
2981                 programCollection.glslSources.add("comp") << glu::ComputeSource(source.str().c_str());
2982         }
2983
2984         deUint32 getInResourceUsageFlags (void) const
2985         {
2986                 return 0;
2987         }
2988
2989         deUint32 getOutResourceUsageFlags (void) const
2990         {
2991                 return VK_IMAGE_USAGE_STORAGE_BIT;
2992         }
2993
2994         VkQueueFlags getQueueFlags (const OperationContext&) const
2995         {
2996                 return VK_QUEUE_COMPUTE_BIT;
2997         }
2998
2999         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3000         {
3001                 return de::MovePtr<Operation>(new MSImageImplementation(context, resource));
3002         }
3003
3004         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3005         {
3006                 DE_ASSERT(0);
3007                 return de::MovePtr<Operation>();
3008         }
3009
3010 private:
3011         const ResourceDescription       m_resourceDesc;
3012 };
3013
3014 } // ShaderAccess ns
3015
3016 namespace CopyBufferToImage
3017 {
3018
3019 class WriteImplementation : public Operation
3020 {
3021 public:
3022         WriteImplementation (OperationContext& context, Resource& resource)
3023                 : m_context             (context)
3024                 , m_resource    (resource)
3025                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3026         {
3027                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3028
3029                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
3030                 const VkDevice                  device          = m_context.getDevice();
3031                 Allocator&                              allocator       = m_context.getAllocator();
3032
3033                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3034                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3035
3036                 const Allocation& alloc = m_hostBuffer->getAllocation();
3037                 fillPattern(alloc.getHostPtr(), m_bufferSize);
3038                 flushAlloc(vk, device, alloc);
3039         }
3040
3041         void recordCommands (const VkCommandBuffer cmdBuffer)
3042         {
3043                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3044                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3045                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3046
3047                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3048                         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                        // VkPipelineStageFlags2KHR                     srcStageMask
3049                         (VkAccessFlags)0,                                                                       // VkAccessFlags2KHR                            srcAccessMask
3050                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                           // VkPipelineStageFlags2KHR                     dstStageMask
3051                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                     // VkAccessFlags2KHR                            dstAccessMask
3052                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        oldLayout
3053                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                                        newLayout
3054                         m_resource.getImage().handle,                                           // VkImage                                                      image
3055                         m_resource.getImage().subresourceRange                          // VkImageSubresourceRange                      subresourceRange
3056                 );
3057                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3058                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3059
3060                 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3061         }
3062
3063         SyncInfo getInSyncInfo (void) const
3064         {
3065                 return emptySyncInfo;
3066         }
3067
3068         SyncInfo getOutSyncInfo (void) const
3069         {
3070                 const SyncInfo syncInfo =
3071                 {
3072                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3073                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
3074                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
3075                 };
3076                 return syncInfo;
3077         }
3078
3079         Data getData (void) const
3080         {
3081                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3082         }
3083
3084         void setData (const Data& data)
3085         {
3086                 setHostBufferData(m_context, *m_hostBuffer, data);
3087         }
3088
3089 private:
3090         OperationContext&               m_context;
3091         Resource&                               m_resource;
3092         de::MovePtr<Buffer>             m_hostBuffer;
3093         const VkDeviceSize              m_bufferSize;
3094 };
3095
3096 class ReadImplementation : public Operation
3097 {
3098 public:
3099         ReadImplementation (OperationContext& context, Resource& resource)
3100                 : m_context                             (context)
3101                 , m_resource                    (resource)
3102                 , m_subresourceRange    (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3103                 , m_subresourceLayers   (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3104         {
3105                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3106
3107                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
3108                 const VkDevice                  device          = m_context.getDevice();
3109                 Allocator&                              allocator       = m_context.getAllocator();
3110                 const VkFormat                  format          = VK_FORMAT_R8G8B8A8_UNORM;
3111                 const deUint32                  pixelSize       = tcu::getPixelSize(mapVkFormat(format));
3112
3113                 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3114                 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);  // there may be some unused space at the end
3115
3116                 // Copy destination image.
3117                 m_image = de::MovePtr<Image>(new Image(
3118                         vk, device, allocator,
3119                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format,
3120                                                                 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3121                                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3122                         MemoryRequirement::Any));
3123
3124                 // Image data will be copied here, so it can be read on the host.
3125                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3126                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3127         }
3128
3129         void recordCommands (const VkCommandBuffer cmdBuffer)
3130         {
3131                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3132                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3133                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3134
3135                 // Resource -> Image
3136                 {
3137                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3138                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                        // VkPipelineStageFlags2KHR                     srcStageMask
3139                                 (VkAccessFlags)0,                                                                       // VkAccessFlags2KHR                            srcAccessMask
3140                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                           // VkPipelineStageFlags2KHR                     dstStageMask
3141                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                     // VkAccessFlags2KHR                            dstAccessMask
3142                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        oldLayout
3143                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                                        newLayout
3144                                 **m_image,                                                                                      // VkImage                                                      image
3145                                 m_subresourceRange                                                                      // VkImageSubresourceRange                      subresourceRange
3146                         );
3147                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3148                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3149
3150                         vk.cmdCopyBufferToImage(cmdBuffer, m_resource.getBuffer().handle, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3151                 }
3152                 // Image -> Host buffer
3153                 {
3154                         const VkImageMemoryBarrier2KHR imageLayoutBarrier2 = makeImageMemoryBarrier2(
3155                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                           // VkPipelineStageFlags2KHR                     srcStageMask
3156                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                     // VkAccessFlags2KHR                            srcAccessMask
3157                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                           // VkPipelineStageFlags2KHR                     dstStageMask
3158                                 VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                                      // VkAccessFlags2KHR                            dstAccessMask
3159                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                                        oldLayout
3160                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                           // VkImageLayout                                        newLayout
3161                                 **m_image,                                                                                      // VkImage                                                      image
3162                                 m_subresourceRange                                                                      // VkImageSubresourceRange                      subresourceRange
3163                         );
3164                         VkDependencyInfoKHR layoutDependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageLayoutBarrier2);
3165                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &layoutDependencyInfo);
3166
3167                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
3168
3169                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3170                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                           // VkPipelineStageFlags2KHR                     srcStageMask
3171                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                                     // VkAccessFlags2KHR                            srcAccessMask
3172                                 VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                                       // VkPipelineStageFlags2KHR                     dstStageMask
3173                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                                          // VkAccessFlags2KHR                            dstAccessMask
3174                                 **m_hostBuffer,                                                                         // VkBuffer                                                     buffer
3175                                 0u,                                                                                                     // VkDeviceSize                                         offset
3176                                 m_resource.getBuffer().size                                                     // VkDeviceSize                                         size
3177                         );
3178                         VkDependencyInfoKHR bufferDependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3179                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &bufferDependencyInfo);
3180                 }
3181         }
3182
3183         SyncInfo getInSyncInfo (void) const
3184         {
3185                 const SyncInfo syncInfo =
3186                 {
3187                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3188                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
3189                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
3190                 };
3191                 return syncInfo;
3192         }
3193
3194         SyncInfo getOutSyncInfo (void) const
3195         {
3196                 return emptySyncInfo;
3197         }
3198
3199         Data getData (void) const
3200         {
3201                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3202         }
3203
3204         void setData (const Data& data)
3205         {
3206                 setHostBufferData(m_context, *m_hostBuffer, data);
3207         }
3208
3209 private:
3210         OperationContext&                               m_context;
3211         Resource&                                               m_resource;
3212         const VkImageSubresourceRange   m_subresourceRange;
3213         const VkImageSubresourceLayers  m_subresourceLayers;
3214         de::MovePtr<Buffer>                             m_hostBuffer;
3215         de::MovePtr<Image>                              m_image;
3216         VkExtent3D                                              m_imageExtent;
3217 };
3218
3219 class Support : public OperationSupport
3220 {
3221 public:
3222         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3223                 : m_mode                                (mode)
3224                 , m_resourceType                (resourceDesc.type)
3225                 , m_requiredQueueFlags  (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3226         {
3227                 // From spec:
3228                 //   Because depth or stencil aspect buffer to image copies may require format conversions on some implementations,
3229                 //   they are not supported on queues that do not support graphics.
3230
3231                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3232                 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3233                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3234         }
3235
3236         deUint32 getInResourceUsageFlags (void) const
3237         {
3238                 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3239                         return m_mode == ACCESS_MODE_READ ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0;
3240                 else
3241                         return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3242         }
3243
3244         deUint32 getOutResourceUsageFlags (void) const
3245         {
3246                 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3247                         return m_mode == ACCESS_MODE_WRITE ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0;
3248                 else
3249                         return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3250         }
3251
3252         VkQueueFlags getQueueFlags (const OperationContext& context) const
3253         {
3254                 DE_UNREF(context);
3255                 return m_requiredQueueFlags;
3256         }
3257
3258         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3259         {
3260                 if (m_mode == ACCESS_MODE_READ)
3261                         return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3262                 else
3263                         return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3264         }
3265
3266         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3267         {
3268                 DE_ASSERT(0);
3269                 return de::MovePtr<Operation>();
3270         }
3271
3272 private:
3273         const AccessMode                        m_mode;
3274         const enum ResourceType         m_resourceType;
3275         const VkQueueFlags                      m_requiredQueueFlags;
3276 };
3277
3278 class CopyImplementation : public Operation
3279 {
3280 public:
3281         CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3282                 : m_context             (context)
3283                 , m_inResource  (inResource)
3284                 , m_outResource (outResource)
3285         {
3286                 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_BUFFER);
3287                 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_IMAGE);
3288         }
3289
3290         void recordCommands (const VkCommandBuffer cmdBuffer)
3291         {
3292                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3293                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_outResource.getImage().extent, m_outResource.getImage().subresourceLayers);
3294                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3295
3296                 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3297                         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3298                         (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3299                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3300                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                              // VkAccessFlags2KHR                            dstAccessMask
3301                         m_inResource.getBuffer().handle,                                // VkBuffer                                                     buffer
3302                         0u,                                                                                             // VkDeviceSize                                         offset
3303                         m_inResource.getBuffer().size                                   // VkDeviceSize                                         size
3304                 );
3305                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3306                         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3307                         (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3308                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3309                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
3310                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
3311                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
3312                         m_outResource.getImage().handle,                                // VkImage                                                      image
3313                         m_outResource.getImage().subresourceRange               // VkImageSubresourceRange                      subresourceRange
3314                 );
3315                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3316                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3317
3318                 vk.cmdCopyBufferToImage(cmdBuffer, m_inResource.getBuffer().handle, m_outResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3319         }
3320
3321         SyncInfo getInSyncInfo (void) const
3322         {
3323                 const SyncInfo syncInfo =
3324                 {
3325                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3326                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
3327                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout                        imageLayout;
3328                 };
3329                 return syncInfo;
3330         }
3331
3332         SyncInfo getOutSyncInfo (void) const
3333         {
3334                 const SyncInfo syncInfo =
3335                 {
3336                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3337                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
3338                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
3339                 };
3340                 return syncInfo;
3341         }
3342
3343         Data getData (void) const
3344         {
3345                 Data data = { 0, DE_NULL };
3346                 return data;
3347         }
3348
3349         void setData (const Data&)
3350         {
3351                 DE_ASSERT(0);
3352         }
3353
3354 private:
3355         OperationContext&               m_context;
3356         Resource&                               m_inResource;
3357         Resource&                               m_outResource;
3358 };
3359
3360 class CopySupport : public OperationSupport
3361 {
3362 public:
3363         CopySupport (const ResourceDescription& resourceDesc)
3364                 : m_resourceType                (resourceDesc.type)
3365                 , m_requiredQueueFlags  (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3366         {
3367         }
3368
3369         deUint32 getInResourceUsageFlags (void) const
3370         {
3371                 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3372                         return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3373                 else
3374                         return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3375         }
3376
3377         deUint32 getOutResourceUsageFlags (void) const
3378         {
3379                 if (m_resourceType == RESOURCE_TYPE_IMAGE)
3380                         return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3381                 else
3382                         return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3383         }
3384
3385         VkQueueFlags getQueueFlags (const OperationContext& context) const
3386         {
3387                 DE_UNREF(context);
3388                 return m_requiredQueueFlags;
3389         }
3390
3391         de::MovePtr<Operation> build (OperationContext&, Resource&) const
3392         {
3393                 DE_ASSERT(0);
3394                 return de::MovePtr<Operation>();
3395         }
3396
3397         de::MovePtr<Operation> build (OperationContext& context, Resource& inResource, Resource& outResource) const
3398         {
3399                 return de::MovePtr<Operation>(new CopyImplementation(context, inResource, outResource));
3400         }
3401
3402 private:
3403         const enum ResourceType         m_resourceType;
3404         const VkQueueFlags                      m_requiredQueueFlags;
3405 };
3406
3407 } // CopyBufferToImage ns
3408
3409 namespace CopyImageToBuffer
3410 {
3411
3412 class WriteImplementation : public Operation
3413 {
3414 public:
3415         WriteImplementation (OperationContext& context, Resource& resource)
3416                 : m_context                             (context)
3417                 , m_resource                    (resource)
3418                 , m_subresourceRange    (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3419                 , m_subresourceLayers   (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3420         {
3421                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
3422
3423                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
3424                 const VkDevice                  device          = m_context.getDevice();
3425                 Allocator&                              allocator       = m_context.getAllocator();
3426                 const VkFormat                  format          = VK_FORMAT_R8G8B8A8_UNORM;
3427                 const deUint32                  pixelSize       = tcu::getPixelSize(mapVkFormat(format));
3428
3429                 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
3430                 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);
3431
3432                 // Source data staging buffer
3433                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3434                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
3435
3436                 const Allocation& alloc = m_hostBuffer->getAllocation();
3437                 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
3438                 flushAlloc(vk, device, alloc);
3439
3440                 // Source data image
3441                 m_image = de::MovePtr<Image>(new Image(
3442                         vk, device, allocator,
3443                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
3444                                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
3445                         MemoryRequirement::Any));
3446         }
3447
3448         void recordCommands (const VkCommandBuffer cmdBuffer)
3449         {
3450                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3451                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_imageExtent, m_subresourceLayers);
3452                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3453
3454                 // Host buffer -> Image
3455                 {
3456                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3457                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3458                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3459                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3460                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
3461                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
3462                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
3463                                 **m_image,                                                                              // VkImage                                                      image
3464                                 m_subresourceRange                                                              // VkImageSubresourceRange                      subresourceRange
3465                         );
3466                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3467                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3468
3469                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
3470                 }
3471                 // Image -> Resource
3472                 {
3473                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3474                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     srcStageMask
3475                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            srcAccessMask
3476                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3477                                 VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                              // VkAccessFlags2KHR                            dstAccessMask
3478                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        oldLayout
3479                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                                        newLayout
3480                                 **m_image,                                                                              // VkImage                                                      image
3481                                 m_subresourceRange                                                              // VkImageSubresourceRange                      subresourceRange
3482                         );
3483                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3484                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3485
3486                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getBuffer().handle, 1u, &copyRegion);
3487                 }
3488         }
3489
3490         SyncInfo getInSyncInfo (void) const
3491         {
3492                 return emptySyncInfo;
3493         }
3494
3495         SyncInfo getOutSyncInfo (void) const
3496         {
3497                 const SyncInfo syncInfo =
3498                 {
3499                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,           // VkPipelineStageFlags         stageMask;
3500                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                     // VkAccessFlags                        accessMask;
3501                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        imageLayout;
3502                 };
3503                 return syncInfo;
3504         }
3505
3506         Data getData (void) const
3507         {
3508                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
3509         }
3510
3511         void setData (const Data& data)
3512         {
3513                 setHostBufferData(m_context, *m_hostBuffer, data);
3514         }
3515
3516 private:
3517         OperationContext&                               m_context;
3518         Resource&                                               m_resource;
3519         const VkImageSubresourceRange   m_subresourceRange;
3520         const VkImageSubresourceLayers  m_subresourceLayers;
3521         de::MovePtr<Buffer>                             m_hostBuffer;
3522         de::MovePtr<Image>                              m_image;
3523         VkExtent3D                                              m_imageExtent;
3524 };
3525
3526 class ReadImplementation : public Operation
3527 {
3528 public:
3529         ReadImplementation (OperationContext& context, Resource& resource)
3530                 : m_context             (context)
3531                 , m_resource    (resource)
3532                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
3533         {
3534                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
3535
3536                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
3537                 const VkDevice                  device          = m_context.getDevice();
3538                 Allocator&                              allocator       = m_context.getAllocator();
3539
3540                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
3541                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
3542
3543                 const Allocation& alloc = m_hostBuffer->getAllocation();
3544                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
3545                 flushAlloc(vk, device, alloc);
3546         }
3547
3548         void recordCommands (const VkCommandBuffer cmdBuffer)
3549         {
3550                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3551                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_resource.getImage().extent, m_resource.getImage().subresourceLayers);
3552                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3553
3554                 vk.cmdCopyImageToBuffer(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
3555
3556                 // Insert a barrier so data written by the transfer is available to the host
3557                 {
3558                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3559                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     srcStageMask
3560                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            srcAccessMask
3561                                 VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                               // VkPipelineStageFlags2KHR                     dstStageMask
3562                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                                  // VkAccessFlags2KHR                            dstAccessMask
3563                                 **m_hostBuffer,                                                                 // VkBuffer                                                     buffer
3564                                 0u,                                                                                             // VkDeviceSize                                         offset
3565                                 VK_WHOLE_SIZE                                                                   // VkDeviceSize                                         size
3566                         );
3567                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
3568                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3569                 }
3570         }
3571
3572         SyncInfo getInSyncInfo (void) const
3573         {
3574                 const SyncInfo syncInfo =
3575                 {
3576                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3577                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
3578                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout                        imageLayout;
3579                 };
3580                 return syncInfo;
3581         }
3582
3583         SyncInfo getOutSyncInfo (void) const
3584         {
3585                 return emptySyncInfo;
3586         }
3587
3588         Data getData (void) const
3589         {
3590                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
3591         }
3592
3593         void setData (const Data&)
3594         {
3595                 DE_ASSERT(0);
3596         }
3597
3598 private:
3599         OperationContext&               m_context;
3600         Resource&                               m_resource;
3601         de::MovePtr<Buffer>             m_hostBuffer;
3602         const VkDeviceSize              m_bufferSize;
3603 };
3604
3605 class CopyImplementation : public Operation
3606 {
3607 public:
3608         CopyImplementation (OperationContext& context, Resource& inResource, Resource& outResource)
3609                 : m_context                             (context)
3610                 , m_inResource                  (inResource)
3611                 , m_outResource                 (outResource)
3612                 , m_subresourceRange    (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
3613                 , m_subresourceLayers   (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
3614         {
3615                 DE_ASSERT(m_inResource.getType() == RESOURCE_TYPE_IMAGE);
3616                 DE_ASSERT(m_outResource.getType() == RESOURCE_TYPE_BUFFER);
3617         }
3618
3619         void recordCommands (const VkCommandBuffer cmdBuffer)
3620         {
3621                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3622                 const VkBufferImageCopy         copyRegion                              = makeBufferImageCopy(m_inResource.getImage().extent, m_subresourceLayers);
3623                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3624
3625                 {
3626                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3627                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3628                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3629                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3630                                 VK_ACCESS_2_TRANSFER_READ_BIT_KHR,                              // VkAccessFlags2KHR                            dstAccessMask
3631                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
3632                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
3633                                 m_inResource.getImage().handle,                                 // VkImage                                                      image
3634                                 m_inResource.getImage().subresourceRange                // VkImageSubresourceRange                      subresourceRange
3635                         );
3636                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
3637                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3638                                 (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3639                                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                   // VkPipelineStageFlags2KHR                     dstStageMask
3640                                 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
3641                                 m_outResource.getBuffer().handle,                               // VkBuffer                                                     buffer
3642                                 0u,                                                                                             // VkDeviceSize                                         offset
3643                                 m_outResource.getBuffer().size                                  // VkDeviceSize                                         size
3644                         );
3645                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2, &imageMemoryBarrier2);
3646                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3647                 }
3648
3649                 vk.cmdCopyImageToBuffer(cmdBuffer, m_inResource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_outResource.getBuffer().handle, 1u, &copyRegion);
3650         }
3651
3652         SyncInfo getInSyncInfo (void) const
3653         {
3654                 const SyncInfo syncInfo =
3655                 {
3656                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3657                         VK_ACCESS_2_TRANSFER_READ_BIT_KHR,              // VkAccessFlags                        accessMask;
3658                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
3659                 };
3660                 return syncInfo;
3661         }
3662
3663         SyncInfo getOutSyncInfo (void) const
3664         {
3665                 const SyncInfo syncInfo =
3666                 {
3667                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
3668                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
3669                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
3670                 };
3671                 return syncInfo;
3672         }
3673
3674         Data getData (void) const
3675         {
3676                 Data data = { 0, DE_NULL };
3677                 return data;
3678         }
3679
3680         void setData (const Data&)
3681         {
3682                 DE_ASSERT(0);
3683         }
3684
3685 private:
3686         OperationContext&                               m_context;
3687         Resource&                                               m_inResource;
3688         Resource&                                               m_outResource;
3689         const VkImageSubresourceRange   m_subresourceRange;
3690         const VkImageSubresourceLayers  m_subresourceLayers;
3691 };
3692
3693 class Support : public OperationSupport
3694 {
3695 public:
3696         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
3697                 : m_mode                                (mode)
3698                 , m_requiredQueueFlags  (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
3699         {
3700                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
3701                 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_IMAGE);
3702                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_BUFFER);
3703         }
3704
3705         deUint32 getInResourceUsageFlags (void) const
3706         {
3707                 return m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0;
3708         }
3709
3710         deUint32 getOutResourceUsageFlags (void) const
3711         {
3712                 return m_mode == ACCESS_MODE_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0;
3713         }
3714
3715         VkQueueFlags getQueueFlags (const OperationContext& context) const
3716         {
3717                 DE_UNREF(context);
3718                 return m_requiredQueueFlags;
3719         }
3720
3721         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3722         {
3723                 if (m_mode == ACCESS_MODE_READ)
3724                         return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3725                 else
3726                         return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3727         }
3728
3729         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3730         {
3731                 DE_ASSERT(0);
3732                 return de::MovePtr<Operation>();
3733         }
3734
3735 private:
3736         const AccessMode                        m_mode;
3737         const VkQueueFlags                      m_requiredQueueFlags;
3738 };
3739
3740 } // CopyImageToBuffer ns
3741
3742 namespace ClearImage
3743 {
3744
3745 enum ClearMode
3746 {
3747         CLEAR_MODE_COLOR,
3748         CLEAR_MODE_DEPTH_STENCIL,
3749 };
3750
3751 class Implementation : public Operation
3752 {
3753 public:
3754         Implementation (OperationContext& context, Resource& resource, const ClearMode mode)
3755                 : m_context             (context)
3756                 , m_resource    (resource)
3757                 , m_clearValue  (makeClearValue(m_resource.getImage().format))
3758                 , m_mode                (mode)
3759         {
3760                 const VkDeviceSize                      size            = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
3761                 const VkExtent3D&                       extent          = m_resource.getImage().extent;
3762                 const VkFormat                          format          = m_resource.getImage().format;
3763                 const tcu::TextureFormat        texFormat       = mapVkFormat(format);
3764
3765                 m_data.resize(static_cast<std::size_t>(size));
3766                 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
3767                 clearPixelBuffer(imagePixels, m_clearValue);
3768         }
3769
3770         void recordCommands (const VkCommandBuffer cmdBuffer)
3771         {
3772                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3773                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3774
3775                 VkPipelineStageFlags2KHR dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3776                 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3777                         dstStageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3778
3779                 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3780                         VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                // VkPipelineStageFlags2KHR                     srcStageMask
3781                         (VkAccessFlags)0,                                                               // VkAccessFlags2KHR                            srcAccessMask
3782                         dstStageMask,                                                                   // VkPipelineStageFlags2KHR                     dstStageMask
3783                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
3784                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                                        oldLayout
3785                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                   // VkImageLayout                                        newLayout
3786                         m_resource.getImage().handle,                                   // VkImage                                                      image
3787                         m_resource.getImage().subresourceRange                  // VkImageSubresourceRange                      subresourceRange
3788                 );
3789                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3790                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3791
3792                 if (m_mode == CLEAR_MODE_COLOR)
3793                         vk.cmdClearColorImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.color, 1u, &m_resource.getImage().subresourceRange);
3794                 else
3795                         vk.cmdClearDepthStencilImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.depthStencil, 1u, &m_resource.getImage().subresourceRange);
3796         }
3797
3798         SyncInfo getInSyncInfo (void) const
3799         {
3800                 return emptySyncInfo;
3801         }
3802
3803         SyncInfo getOutSyncInfo (void) const
3804         {
3805                 VkPipelineStageFlags2KHR stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
3806                 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
3807                         stageMask = VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR;
3808
3809                 return
3810                 {
3811                         stageMask,                                                              // VkPipelineStageFlags         stageMask;
3812                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
3813                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
3814                 };
3815         }
3816
3817         Data getData (void) const
3818         {
3819                 const Data data =
3820                 {
3821                         m_data.size(),          // std::size_t          size;
3822                         &m_data[0],                     // const deUint8*       data;
3823                 };
3824                 return data;
3825         }
3826
3827         void setData (const Data&)
3828         {
3829                 DE_ASSERT(0);
3830         }
3831
3832 private:
3833         OperationContext&               m_context;
3834         Resource&                               m_resource;
3835         std::vector<deUint8>    m_data;
3836         const VkClearValue              m_clearValue;
3837         const ClearMode                 m_mode;
3838 };
3839
3840 class Support : public OperationSupport
3841 {
3842 public:
3843         Support (const ResourceDescription& resourceDesc, const ClearMode mode)
3844                 : m_resourceDesc        (resourceDesc)
3845                 , m_mode                        (mode)
3846         {
3847                 DE_ASSERT(m_mode == CLEAR_MODE_COLOR || m_mode == CLEAR_MODE_DEPTH_STENCIL);
3848                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
3849                 DE_ASSERT(m_resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT || (m_mode != CLEAR_MODE_COLOR));
3850                 DE_ASSERT((m_resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) || (m_mode != CLEAR_MODE_DEPTH_STENCIL));
3851         }
3852
3853         deUint32 getInResourceUsageFlags (void) const
3854         {
3855                 return 0;
3856         }
3857
3858         deUint32 getOutResourceUsageFlags (void) const
3859         {
3860                 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3861         }
3862
3863         VkQueueFlags getQueueFlags (const OperationContext& context) const
3864         {
3865                 DE_UNREF(context);
3866                 if (m_mode == CLEAR_MODE_COLOR)
3867                         return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
3868                 else
3869                         return VK_QUEUE_GRAPHICS_BIT;
3870         }
3871
3872         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3873         {
3874                 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
3875         }
3876
3877         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
3878         {
3879                 DE_ASSERT(0);
3880                 return de::MovePtr<Operation>();
3881         }
3882
3883 private:
3884         const ResourceDescription       m_resourceDesc;
3885         const ClearMode                         m_mode;
3886 };
3887
3888 } // ClearImage ns
3889
3890 namespace Draw
3891 {
3892
3893 enum DrawCall
3894 {
3895         DRAW_CALL_DRAW,
3896         DRAW_CALL_DRAW_INDEXED,
3897         DRAW_CALL_DRAW_INDIRECT,
3898         DRAW_CALL_DRAW_INDEXED_INDIRECT,
3899 };
3900
3901 //! A write operation that is a result of drawing to an image.
3902 //! \todo Add support for depth/stencil too?
3903 class Implementation : public Operation
3904 {
3905 public:
3906         Implementation (OperationContext& context, Resource& resource, const DrawCall drawCall)
3907                 : m_context             (context)
3908                 , m_resource    (resource)
3909                 , m_drawCall    (drawCall)
3910                 , m_vertices    (context)
3911         {
3912                 const DeviceInterface&          vk                              = context.getDeviceInterface();
3913                 const VkDevice                          device                  = context.getDevice();
3914                 Allocator&                                      allocator               = context.getAllocator();
3915
3916                 // Indirect buffer
3917
3918                 if (m_drawCall == DRAW_CALL_DRAW_INDIRECT)
3919                 {
3920                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3921                                 makeBufferCreateInfo(sizeof(VkDrawIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3922
3923                         const Allocation&                               alloc                           = m_indirectBuffer->getAllocation();
3924                         VkDrawIndirectCommand* const    pIndirectCommand        = static_cast<VkDrawIndirectCommand*>(alloc.getHostPtr());
3925
3926                         pIndirectCommand->vertexCount   = m_vertices.getNumVertices();
3927                         pIndirectCommand->instanceCount = 1u;
3928                         pIndirectCommand->firstVertex   = 0u;
3929                         pIndirectCommand->firstInstance = 0u;
3930
3931                         flushAlloc(vk, device, alloc);
3932                 }
3933                 else if (m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
3934                 {
3935                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3936                                 makeBufferCreateInfo(sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
3937
3938                         const Allocation&                                       alloc                           = m_indirectBuffer->getAllocation();
3939                         VkDrawIndexedIndirectCommand* const     pIndirectCommand        = static_cast<VkDrawIndexedIndirectCommand*>(alloc.getHostPtr());
3940
3941                         pIndirectCommand->indexCount    = m_vertices.getNumIndices();
3942                         pIndirectCommand->instanceCount = 1u;
3943                         pIndirectCommand->firstIndex    = 0u;
3944                         pIndirectCommand->vertexOffset  = 0u;
3945                         pIndirectCommand->firstInstance = 0u;
3946
3947                         flushAlloc(vk, device, alloc);
3948                 }
3949
3950                 // Resource image is the color attachment
3951
3952                 m_colorFormat                   = m_resource.getImage().format;
3953                 m_colorSubresourceRange = m_resource.getImage().subresourceRange;
3954                 m_colorImage                    = m_resource.getImage().handle;
3955                 m_attachmentExtent              = m_resource.getImage().extent;
3956
3957                 // Pipeline
3958
3959                 m_colorAttachmentView   = makeImageView         (vk, device, m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
3960                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
3961                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_attachmentExtent.width, m_attachmentExtent.height);
3962                 m_pipelineLayout                = makePipelineLayout(vk, device);
3963
3964                 GraphicsPipelineBuilder pipelineBuilder;
3965                 pipelineBuilder
3966                         .setRenderSize                                  (tcu::IVec2(m_attachmentExtent.width, m_attachmentExtent.height))
3967                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
3968                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get("draw_vert"), DE_NULL)
3969                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get("draw_frag"), DE_NULL);
3970
3971                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
3972
3973                 // Set expected draw values
3974
3975                 m_expectedData.resize(static_cast<size_t>(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent)));
3976                 tcu::PixelBufferAccess imagePixels(mapVkFormat(m_colorFormat), m_attachmentExtent.width, m_attachmentExtent.height, m_attachmentExtent.depth, &m_expectedData[0]);
3977                 clearPixelBuffer(imagePixels, makeClearValue(m_colorFormat));
3978         }
3979
3980         void recordCommands (const VkCommandBuffer cmdBuffer)
3981         {
3982                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
3983                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
3984
3985                 // Change color attachment image layout
3986                 {
3987                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
3988                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                                // VkPipelineStageFlags2KHR                     srcStageMask
3989                                 (VkAccessFlags)0,                                                                               // VkAccessFlags2KHR                            srcAccessMask
3990                                 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,    // VkPipelineStageFlags2KHR                     dstStageMask
3991                                 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
3992                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                                        oldLayout
3993                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                               // VkImageLayout                                        newLayout
3994                                 m_colorImage,                                                                                   // VkImage                                                      image
3995                                 m_colorSubresourceRange                                                                 // VkImageSubresourceRange                      subresourceRange
3996                         );
3997                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
3998                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
3999                 }
4000
4001                 {
4002                         const VkRect2D  renderArea      = makeRect2D(m_attachmentExtent);
4003                         const tcu::Vec4 clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4004
4005                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4006                 }
4007
4008                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4009                 {
4010                         const VkDeviceSize      vertexBufferOffset      = 0ull;
4011                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
4012                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4013                 }
4014
4015                 if (m_drawCall == DRAW_CALL_DRAW_INDEXED || m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
4016                         vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4017
4018                 switch (m_drawCall)
4019                 {
4020                         case DRAW_CALL_DRAW:
4021                                 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
4022                                 break;
4023
4024                         case DRAW_CALL_DRAW_INDEXED:
4025                                 vk.cmdDrawIndexed(cmdBuffer, m_vertices.getNumIndices(), 1u, 0u, 0, 0u);
4026                                 break;
4027
4028                         case DRAW_CALL_DRAW_INDIRECT:
4029                                 vk.cmdDrawIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4030                                 break;
4031
4032                         case DRAW_CALL_DRAW_INDEXED_INDIRECT:
4033                                 vk.cmdDrawIndexedIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
4034                                 break;
4035                 }
4036
4037                 endRenderPass(vk, cmdBuffer);
4038         }
4039
4040         SyncInfo getInSyncInfo (void) const
4041         {
4042                 return emptySyncInfo;
4043         }
4044
4045         SyncInfo getOutSyncInfo (void) const
4046         {
4047                 const SyncInfo syncInfo =
4048                 {
4049                         VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,    // VkPipelineStageFlags         stageMask;
4050                         VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,                             // VkAccessFlags                        accessMask;
4051                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                               // VkImageLayout                        imageLayout;
4052                 };
4053                 return syncInfo;
4054         }
4055
4056         Data getData (void) const
4057         {
4058                 const Data data =
4059                 {
4060                         m_expectedData.size(),          // std::size_t          size;
4061                         &m_expectedData[0],                     // const deUint8*       data;
4062                 };
4063                 return data;
4064         }
4065
4066         void setData (const Data& data)
4067         {
4068                 DE_ASSERT(m_expectedData.size() == data.size);
4069                 deMemcpy(&m_expectedData[0], data.data, data.size);
4070         }
4071
4072 private:
4073         OperationContext&                       m_context;
4074         Resource&                                       m_resource;
4075         const DrawCall                          m_drawCall;
4076         const VertexGrid                        m_vertices;
4077         std::vector<deUint8>            m_expectedData;
4078         de::MovePtr<Buffer>                     m_indirectBuffer;
4079         VkFormat                                        m_colorFormat;
4080         VkImage                                         m_colorImage;
4081         Move<VkImageView>                       m_colorAttachmentView;
4082         VkImageSubresourceRange         m_colorSubresourceRange;
4083         VkExtent3D                                      m_attachmentExtent;
4084         Move<VkRenderPass>                      m_renderPass;
4085         Move<VkFramebuffer>                     m_framebuffer;
4086         Move<VkPipelineLayout>          m_pipelineLayout;
4087         Move<VkPipeline>                        m_pipeline;
4088 };
4089
4090 template<typename T, std::size_t N>
4091 std::string toString (const T (&values)[N])
4092 {
4093         std::ostringstream str;
4094         for (std::size_t i = 0; i < N; ++i)
4095                 str << (i != 0 ? ", " : "") << values[i];
4096         return str.str();
4097 }
4098
4099 class Support : public OperationSupport
4100 {
4101 public:
4102         Support (const ResourceDescription& resourceDesc, const DrawCall drawCall)
4103                 : m_resourceDesc        (resourceDesc)
4104                 , m_drawCall            (drawCall)
4105         {
4106                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE && m_resourceDesc.imageType == VK_IMAGE_TYPE_2D);
4107                 DE_ASSERT(!isDepthStencilFormat(m_resourceDesc.imageFormat));
4108         }
4109
4110         void initPrograms (SourceCollections& programCollection) const
4111         {
4112                 // Vertex
4113                 {
4114                         std::ostringstream src;
4115                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4116                                 << "\n"
4117                                 << "layout(location = 0) in vec4 v_in_position;\n"
4118                                 << "\n"
4119                                 << "out " << s_perVertexBlock << ";\n"
4120                                 << "\n"
4121                                 << "void main (void)\n"
4122                                 << "{\n"
4123                                 << "    gl_Position = v_in_position;\n"
4124                                 << "}\n";
4125
4126                         programCollection.glslSources.add("draw_vert") << glu::VertexSource(src.str());
4127                 }
4128
4129                 // Fragment
4130                 {
4131                         const VkClearValue      clearValue              = makeClearValue(m_resourceDesc.imageFormat);
4132                         const bool                      isIntegerFormat = isIntFormat(m_resourceDesc.imageFormat) || isUintFormat(m_resourceDesc.imageFormat);
4133                         const std::string       colorType               = (isIntegerFormat ? "uvec4" : "vec4");
4134
4135                         std::ostringstream src;
4136                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4137                                 << "\n"
4138                                 << "layout(location = 0) out " << colorType << " o_color;\n"
4139                                 << "\n"
4140                                 << "void main (void)\n"
4141                                 << "{\n"
4142                                 << "    o_color = " << colorType << "(" << (isIntegerFormat ? toString(clearValue.color.uint32) : toString(clearValue.color.float32)) << ");\n"
4143                                 << "}\n";
4144
4145                         programCollection.glslSources.add("draw_frag") << glu::FragmentSource(src.str());
4146                 }
4147         }
4148
4149         deUint32 getInResourceUsageFlags (void) const
4150         {
4151                 return 0;
4152         }
4153
4154         deUint32 getOutResourceUsageFlags (void) const
4155         {
4156                 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4157         }
4158
4159         VkQueueFlags getQueueFlags (const OperationContext& context) const
4160         {
4161                 DE_UNREF(context);
4162                 return VK_QUEUE_GRAPHICS_BIT;
4163         }
4164
4165         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4166         {
4167                 return de::MovePtr<Operation>(new Implementation(context, resource, m_drawCall));
4168         }
4169
4170         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4171         {
4172                 DE_ASSERT(0);
4173                 return de::MovePtr<Operation>();
4174         }
4175
4176 private:
4177         const ResourceDescription       m_resourceDesc;
4178         const DrawCall                          m_drawCall;
4179 };
4180
4181 } // Draw ns
4182
4183 namespace ClearAttachments
4184 {
4185
4186 class Implementation : public Operation
4187 {
4188 public:
4189         Implementation (OperationContext& context, Resource& resource)
4190                 : m_context             (context)
4191                 , m_resource    (resource)
4192                 , m_clearValue  (makeClearValue(m_resource.getImage().format))
4193         {
4194                 const DeviceInterface&          vk                              = context.getDeviceInterface();
4195                 const VkDevice                          device                  = context.getDevice();
4196
4197                 const VkDeviceSize                      size            = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
4198                 const VkExtent3D&                       extent          = m_resource.getImage().extent;
4199                 const VkFormat                          format          = m_resource.getImage().format;
4200                 const tcu::TextureFormat        texFormat       = mapVkFormat(format);
4201                 const SyncInfo                          syncInfo        = getOutSyncInfo();
4202
4203                 m_data.resize(static_cast<std::size_t>(size));
4204                 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
4205                 clearPixelBuffer(imagePixels, m_clearValue);
4206
4207                 m_attachmentView = makeImageView(vk, device, m_resource.getImage().handle, getImageViewType(m_resource.getImage().imageType), m_resource.getImage().format, m_resource.getImage().subresourceRange);
4208
4209                 switch (m_resource.getImage().subresourceRange.aspectMask)
4210                 {
4211                         case VK_IMAGE_ASPECT_COLOR_BIT:
4212                                 m_renderPass = makeRenderPass(vk, device, m_resource.getImage().format, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_DONT_CARE, syncInfo.imageLayout);
4213                         break;
4214                         case VK_IMAGE_ASPECT_STENCIL_BIT:
4215                         case VK_IMAGE_ASPECT_DEPTH_BIT:
4216                                 m_renderPass = makeRenderPass(vk, device, VK_FORMAT_UNDEFINED, m_resource.getImage().format, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, syncInfo.imageLayout);
4217                         break;
4218                         default:
4219                                 DE_ASSERT(0);
4220                         break;
4221                 }
4222
4223                 m_frameBuffer   = makeFramebuffer(vk, device, *m_renderPass, *m_attachmentView, m_resource.getImage().extent.width, m_resource.getImage().extent.height);
4224         }
4225
4226         void recordCommands (const VkCommandBuffer cmdBuffer)
4227         {
4228                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
4229                 if ((m_resource.getImage().subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
4230                 {
4231                         const VkImageMemoryBarrier imageBarrier =
4232                         {
4233                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // sType
4234                                 DE_NULL,                                                                                        // pNext
4235                                 0u,                                                                                                     // srcAccessMask
4236                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,           // dstAccessMask
4237                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // oldLayout
4238                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // newLayout
4239                                 VK_QUEUE_FAMILY_IGNORED,                                                        // srcQueueFamilyIndex
4240                                 VK_QUEUE_FAMILY_IGNORED,                                                        // dstQueueFamilyIndex
4241                                 m_resource.getImage().handle,                                           // image
4242                                 m_resource.getImage().subresourceRange                          // subresourceRange
4243                         };
4244                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
4245                 }
4246                 beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_frameBuffer, makeRect2D(0 ,0, m_resource.getImage().extent.width, m_resource.getImage().extent.height), m_clearValue);
4247
4248                 const VkClearAttachment clearAttachment =
4249                 {
4250                         m_resource.getImage().subresourceRange.aspectMask,      // VkImageAspectFlags   aspectMask;
4251                         0,                                                                                                      // deUint32                             colorAttachment;
4252                         m_clearValue                                                                            // VkClearValue                 clearValue;
4253                 };
4254
4255                 const VkRect2D                  rect2D                  = makeRect2D(m_resource.getImage().extent);
4256
4257                 const VkClearRect               clearRect               =
4258                 {
4259                         rect2D,                                                                                         // VkRect2D     rect;
4260                         0u,                                                                                                     // deUint32     baseArrayLayer;
4261                         m_resource.getImage().subresourceLayers.layerCount      // deUint32     layerCount;
4262                 };
4263
4264                 vk.cmdClearAttachments(cmdBuffer, 1, &clearAttachment, 1, &clearRect);
4265
4266                 endRenderPass(vk, cmdBuffer);
4267         }
4268
4269         SyncInfo getInSyncInfo (void) const
4270         {
4271                 return emptySyncInfo;
4272         }
4273
4274         SyncInfo getOutSyncInfo (void) const
4275         {
4276                 SyncInfo syncInfo;
4277                 syncInfo.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR;
4278
4279                 switch (m_resource.getImage().subresourceRange.aspectMask)
4280                 {
4281                         case VK_IMAGE_ASPECT_COLOR_BIT:
4282                                 syncInfo.accessMask             = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR;
4283                                 syncInfo.imageLayout    = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4284                         break;
4285                         case VK_IMAGE_ASPECT_STENCIL_BIT:
4286                         case VK_IMAGE_ASPECT_DEPTH_BIT:
4287                                 syncInfo.accessMask             = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR;
4288                                 syncInfo.imageLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4289                         break;
4290                         default:
4291                                 DE_ASSERT(0);
4292                         break;
4293                 }
4294
4295                 return syncInfo;
4296         }
4297
4298         Data getData (void) const
4299         {
4300                 const Data data =
4301                 {
4302                         m_data.size(),  // std::size_t          size;
4303                         &m_data[0],             // const deUint8*       data;
4304                 };
4305                 return data;
4306         }
4307
4308         void setData (const Data&)
4309         {
4310                 DE_ASSERT(0);
4311         }
4312
4313 private:
4314         OperationContext&               m_context;
4315         Resource&                               m_resource;
4316         std::vector<deUint8>    m_data;
4317         const VkClearValue              m_clearValue;
4318         Move<VkImageView>               m_attachmentView;
4319         Move<VkRenderPass>              m_renderPass;
4320         Move<VkFramebuffer>             m_frameBuffer;
4321 };
4322
4323 class Support : public OperationSupport
4324 {
4325 public:
4326         Support (const ResourceDescription& resourceDesc)
4327                 : m_resourceDesc (resourceDesc)
4328         {
4329                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
4330         }
4331
4332         deUint32 getInResourceUsageFlags (void) const
4333         {
4334                 return 0;
4335         }
4336
4337         deUint32 getOutResourceUsageFlags (void) const
4338         {
4339                 switch (m_resourceDesc.imageAspect)
4340                 {
4341                         case VK_IMAGE_ASPECT_COLOR_BIT:
4342                                 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4343                         case VK_IMAGE_ASPECT_STENCIL_BIT:
4344                         case VK_IMAGE_ASPECT_DEPTH_BIT:
4345                                 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
4346                         default:
4347                                 DE_ASSERT(0);
4348                 }
4349                 return 0u;
4350         }
4351
4352         VkQueueFlags getQueueFlags (const OperationContext& context) const
4353         {
4354                 DE_UNREF(context);
4355                 return VK_QUEUE_GRAPHICS_BIT;
4356         }
4357
4358         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4359         {
4360                 return de::MovePtr<Operation>(new Implementation(context, resource));
4361         }
4362
4363         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4364         {
4365                 DE_ASSERT(0);
4366                 return de::MovePtr<Operation>();
4367         }
4368
4369 private:
4370         const ResourceDescription       m_resourceDesc;
4371 };
4372
4373 } // ClearAttachments
4374
4375 namespace IndirectBuffer
4376 {
4377
4378 class GraphicsPipeline : public Pipeline
4379 {
4380 public:
4381         GraphicsPipeline (OperationContext&                             context,
4382                                           const ResourceType                    resourceType,
4383                                           const VkBuffer                                indirectBuffer,
4384                                           const std::string&                    shaderPrefix,
4385                                           const VkDescriptorSetLayout   descriptorSetLayout)
4386                 : m_resourceType        (resourceType)
4387                 , m_indirectBuffer      (indirectBuffer)
4388                 , m_vertices            (context)
4389         {
4390                 const DeviceInterface&          vk                              = context.getDeviceInterface();
4391                 const VkDevice                          device                  = context.getDevice();
4392                 Allocator&                                      allocator               = context.getAllocator();
4393
4394                 // Color attachment
4395
4396                 m_colorFormat                                   = VK_FORMAT_R8G8B8A8_UNORM;
4397                 m_colorImageSubresourceRange    = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4398                 m_colorImageExtent                              = makeExtent3D(16u, 16u, 1u);
4399                 m_colorAttachmentImage                  = de::MovePtr<Image>(new Image(vk, device, allocator,
4400                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4401                                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4402                         MemoryRequirement::Any));
4403
4404                 // Pipeline
4405
4406                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4407                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
4408                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4409                 m_pipelineLayout                = makePipelineLayout(vk, device, descriptorSetLayout);
4410
4411                 GraphicsPipelineBuilder pipelineBuilder;
4412                 pipelineBuilder
4413                         .setRenderSize                                  (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
4414                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
4415                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
4416                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
4417
4418                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
4419         }
4420
4421         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4422         {
4423                 const DeviceInterface&          vk                                              = context.getDeviceInterface();
4424                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(context.getSynchronizationType(), vk, DE_FALSE);
4425
4426                 // Change color attachment image layout
4427                 {
4428                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4429                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                                // VkPipelineStageFlags2KHR                     srcStageMask
4430                                 (VkAccessFlags)0,                                                                               // VkAccessFlags2KHR                            srcAccessMask
4431                                 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,    // VkPipelineStageFlags2KHR                     dstStageMask
4432                                 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
4433                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                                        oldLayout
4434                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                               // VkImageLayout                                        newLayout
4435                                 **m_colorAttachmentImage,                                                               // VkImage                                                      image
4436                                 m_colorImageSubresourceRange                                                    // VkImageSubresourceRange                      subresourceRange
4437                         );
4438                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4439                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4440                 }
4441
4442                 {
4443                         const VkRect2D  renderArea      = makeRect2D(m_colorImageExtent);
4444                         const tcu::Vec4 clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4445
4446                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4447                 }
4448
4449                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4450                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4451                 {
4452                         const VkDeviceSize      vertexBufferOffset      = 0ull;
4453                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
4454                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
4455                 }
4456
4457                 switch (m_resourceType)
4458                 {
4459                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4460                                 vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4461                                 break;
4462
4463                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4464                                 vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
4465                                 vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
4466                                 break;
4467
4468                         default:
4469                                 DE_ASSERT(0);
4470                                 break;
4471                 }
4472                 endRenderPass(vk, cmdBuffer);
4473         }
4474
4475 private:
4476         const ResourceType                      m_resourceType;
4477         const VkBuffer                          m_indirectBuffer;
4478         const VertexGrid                        m_vertices;
4479         VkFormat                                        m_colorFormat;
4480         de::MovePtr<Image>                      m_colorAttachmentImage;
4481         Move<VkImageView>                       m_colorAttachmentView;
4482         VkExtent3D                                      m_colorImageExtent;
4483         VkImageSubresourceRange         m_colorImageSubresourceRange;
4484         Move<VkRenderPass>                      m_renderPass;
4485         Move<VkFramebuffer>                     m_framebuffer;
4486         Move<VkPipelineLayout>          m_pipelineLayout;
4487         Move<VkPipeline>                        m_pipeline;
4488 };
4489
4490 class ComputePipeline : public Pipeline
4491 {
4492 public:
4493         ComputePipeline (OperationContext&                              context,
4494                                          const VkBuffer                                 indirectBuffer,
4495                                          const std::string&                             shaderPrefix,
4496                                          const VkDescriptorSetLayout    descriptorSetLayout)
4497                 : m_indirectBuffer      (indirectBuffer)
4498         {
4499                 const DeviceInterface&  vk              = context.getDeviceInterface();
4500                 const VkDevice                  device  = context.getDevice();
4501
4502                 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
4503
4504                 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
4505                 m_pipeline               = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData());
4506         }
4507
4508         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
4509         {
4510                 const DeviceInterface&  vk      = context.getDeviceInterface();
4511
4512                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
4513                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
4514                 vk.cmdDispatchIndirect(cmdBuffer, m_indirectBuffer, 0u);
4515         }
4516
4517 private:
4518         const VkBuffer                          m_indirectBuffer;
4519         Move<VkPipelineLayout>          m_pipelineLayout;
4520         Move<VkPipeline>                        m_pipeline;
4521 };
4522
4523 //! Read indirect buffer by executing an indirect draw or dispatch command.
4524 class ReadImplementation : public Operation
4525 {
4526 public:
4527         ReadImplementation (OperationContext& context, Resource& resource)
4528                 : m_context                             (context)
4529                 , m_resource                    (resource)
4530                 , m_stage                               (resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT)
4531                 , m_pipelineStage               (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
4532                 , m_hostBufferSizeBytes (sizeof(deUint32))
4533         {
4534                 requireFeaturesForSSBOAccess (m_context, m_stage);
4535
4536                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
4537                 const VkDevice                  device          = m_context.getDevice();
4538                 Allocator&                              allocator       = m_context.getAllocator();
4539
4540                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
4541                         vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4542
4543                 // Init host buffer data
4544                 {
4545                         const Allocation& alloc = m_hostBuffer->getAllocation();
4546                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
4547                         flushAlloc(vk, device, alloc);
4548                 }
4549
4550                 // Prepare descriptors
4551                 {
4552                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4553                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
4554                                 .build(vk, device);
4555
4556                         m_descriptorPool = DescriptorPoolBuilder()
4557                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4558                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4559
4560                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4561
4562                         const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
4563
4564                         DescriptorSetUpdateBuilder()
4565                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
4566                                 .update(vk, device);
4567                 }
4568
4569                 // Create pipeline
4570                 m_pipeline = (m_resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH
4571                         ? de::MovePtr<Pipeline>(new ComputePipeline(context, m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout))
4572                         : de::MovePtr<Pipeline>(new GraphicsPipeline(context, m_resource.getType(), m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout)));
4573         }
4574
4575         void recordCommands (const VkCommandBuffer cmdBuffer)
4576         {
4577                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
4578                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4579
4580                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
4581
4582                 // Insert a barrier so data written by the shader is available to the host
4583                 const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
4584                         m_pipelineStage,                                                        // VkPipelineStageFlags2KHR                     srcStageMask
4585                         VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                       // VkAccessFlags2KHR                            srcAccessMask
4586                         VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                       // VkPipelineStageFlags2KHR                     dstStageMask
4587                         VK_ACCESS_2_HOST_READ_BIT_KHR,                          // VkAccessFlags2KHR                            dstAccessMask
4588                         **m_hostBuffer,                                                         // VkBuffer                                                     buffer
4589                         0u,                                                                                     // VkDeviceSize                                         offset
4590                         m_hostBufferSizeBytes                                           // VkDeviceSize                                         size
4591                 );
4592                 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
4593                 synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4594         }
4595
4596         SyncInfo getInSyncInfo (void) const
4597         {
4598                 const SyncInfo syncInfo =
4599                 {
4600                         VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR,      // VkPipelineStageFlags         stageMask;
4601                         VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR,      // VkAccessFlags                        accessMask;
4602                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        imageLayout;
4603                 };
4604                 return syncInfo;
4605         }
4606
4607         SyncInfo getOutSyncInfo (void) const
4608         {
4609                 return emptySyncInfo;
4610         }
4611
4612         Data getData (void) const
4613         {
4614                 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
4615         }
4616
4617         void setData (const Data&)
4618         {
4619                 DE_ASSERT(0);
4620         }
4621
4622 private:
4623         OperationContext&                       m_context;
4624         Resource&                                       m_resource;
4625         const VkShaderStageFlagBits     m_stage;
4626         const VkPipelineStageFlags      m_pipelineStage;
4627         const VkDeviceSize                      m_hostBufferSizeBytes;
4628         de::MovePtr<Buffer>                     m_hostBuffer;
4629         Move<VkDescriptorPool>          m_descriptorPool;
4630         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
4631         Move<VkDescriptorSet>           m_descriptorSet;
4632         de::MovePtr<Pipeline>           m_pipeline;
4633 };
4634
4635 //! Prepare indirect buffer for a draw/dispatch call.
4636 class WriteImplementation : public Operation
4637 {
4638 public:
4639         WriteImplementation (OperationContext& context, Resource& resource)
4640                 : m_context                     (context)
4641                 , m_resource            (resource)
4642         {
4643                 switch (m_resource.getType())
4644                 {
4645                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
4646                         {
4647                                 m_drawIndirect.vertexCount              = 6u;
4648                                 m_drawIndirect.instanceCount    = 1u;
4649                                 m_drawIndirect.firstVertex              = 0u;
4650                                 m_drawIndirect.firstInstance    = 0u;
4651
4652                                 m_indirectData                                  = reinterpret_cast<deUint32*>(&m_drawIndirect);
4653                                 m_expectedValue                                 = 6u;
4654                         }
4655                         break;
4656
4657                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
4658                         {
4659                                 m_drawIndexedIndirect.indexCount        = 6u;
4660                                 m_drawIndexedIndirect.instanceCount     = 1u;
4661                                 m_drawIndexedIndirect.firstIndex        = 0u;
4662                                 m_drawIndexedIndirect.vertexOffset      = 0u;
4663                                 m_drawIndexedIndirect.firstInstance     = 0u;
4664
4665                                 m_indirectData                                          = reinterpret_cast<deUint32*>(&m_drawIndexedIndirect);
4666                                 m_expectedValue                                         = 6u;
4667                         }
4668                         break;
4669
4670                         case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
4671                         {
4672                                 m_dispatchIndirect.x    = 7u;
4673                                 m_dispatchIndirect.y    = 2u;
4674                                 m_dispatchIndirect.z    = 1u;
4675
4676                                 m_indirectData                  = reinterpret_cast<deUint32*>(&m_dispatchIndirect);
4677                                 m_expectedValue                 = 14u;
4678                         }
4679                         break;
4680
4681                         default:
4682                                 DE_ASSERT(0);
4683                                 break;
4684                 }
4685         }
4686
4687         void recordCommands (const VkCommandBuffer cmdBuffer)
4688         {
4689                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
4690
4691                 vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_indirectData);
4692         }
4693
4694         SyncInfo getInSyncInfo (void) const
4695         {
4696                 return emptySyncInfo;
4697         }
4698
4699         SyncInfo getOutSyncInfo (void) const
4700         {
4701                 const SyncInfo syncInfo =
4702                 {
4703                         VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,   // VkPipelineStageFlags         stageMask;
4704                         VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,             // VkAccessFlags                        accessMask;
4705                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
4706                 };
4707                 return syncInfo;
4708         }
4709
4710         Data getData (void) const
4711         {
4712                 const Data data =
4713                 {
4714                         sizeof(deUint32),                                                                       // std::size_t          size;
4715                         reinterpret_cast<const deUint8*>(&m_expectedValue),     // const deUint8*       data;
4716                 };
4717                 return data;
4718         }
4719
4720         void setData (const Data&)
4721         {
4722                 DE_ASSERT(0);
4723         }
4724
4725 private:
4726         OperationContext&                               m_context;
4727         Resource&                                               m_resource;
4728         VkDrawIndirectCommand                   m_drawIndirect;
4729         VkDrawIndexedIndirectCommand    m_drawIndexedIndirect;
4730         VkDispatchIndirectCommand               m_dispatchIndirect;
4731         deUint32*                                               m_indirectData;
4732         deUint32                                                m_expectedValue;        //! Side-effect value expected to be computed by a read (draw/dispatch) command.
4733 };
4734
4735 class ReadSupport : public OperationSupport
4736 {
4737 public:
4738         ReadSupport (const ResourceDescription& resourceDesc)
4739                 : m_resourceDesc        (resourceDesc)
4740         {
4741                 DE_ASSERT(isIndirectBuffer(m_resourceDesc.type));
4742         }
4743
4744         void initPrograms (SourceCollections& programCollection) const
4745         {
4746                 std::ostringstream decl;
4747                 decl << "layout(set = 0, binding = 0, std140) coherent buffer Data {\n"
4748                          << "    uint value;\n"
4749                          << "} sb_out;\n";
4750
4751                 std::ostringstream main;
4752                 main << "    atomicAdd(sb_out.value, 1u);\n";
4753
4754                 // Vertex
4755                 {
4756                         std::ostringstream src;
4757                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4758                                 << "\n"
4759                                 << "layout(location = 0) in vec4 v_in_position;\n"
4760                                 << "\n"
4761                                 << "out " << s_perVertexBlock << ";\n"
4762                                 << "\n"
4763                                 << decl.str()
4764                                 << "\n"
4765                                 << "void main (void)\n"
4766                                 << "{\n"
4767                                 << "    gl_Position = v_in_position;\n"
4768                                 << main.str()
4769                                 << "}\n";
4770
4771                         programCollection.glslSources.add("read_ib_vert") << glu::VertexSource(src.str());
4772                 }
4773
4774                 // Fragment
4775                 {
4776                         std::ostringstream src;
4777                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4778                                 << "\n"
4779                                 << "layout(location = 0) out vec4 o_color;\n"
4780                                 << "\n"
4781                                 << "void main (void)\n"
4782                                 << "{\n"
4783                                 << "    o_color = vec4(1.0);\n"
4784                                 << "}\n";
4785
4786                         programCollection.glslSources.add("read_ib_frag") << glu::FragmentSource(src.str());
4787                 }
4788
4789                 // Compute
4790                 {
4791                         std::ostringstream src;
4792                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
4793                                 << "\n"
4794                                 << "layout(local_size_x = 1) in;\n"
4795                                 << "\n"
4796                                 << decl.str()
4797                                 << "\n"
4798                                 << "void main (void)\n"
4799                                 << "{\n"
4800                                 << main.str()
4801                                 << "}\n";
4802
4803                         programCollection.glslSources.add("read_ib_comp") << glu::ComputeSource(src.str());
4804                 }
4805         }
4806
4807         deUint32 getInResourceUsageFlags (void) const
4808         {
4809                 return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
4810         }
4811
4812         deUint32 getOutResourceUsageFlags (void) const
4813         {
4814                 return 0;
4815         }
4816
4817         VkQueueFlags getQueueFlags (const OperationContext& context) const
4818         {
4819                 DE_UNREF(context);
4820                 return (m_resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
4821         }
4822
4823         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4824         {
4825                 return de::MovePtr<Operation>(new ReadImplementation(context, resource));
4826         }
4827
4828         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4829         {
4830                 DE_ASSERT(0);
4831                 return de::MovePtr<Operation>();
4832         }
4833
4834 private:
4835         const ResourceDescription       m_resourceDesc;
4836 };
4837
4838
4839 class WriteSupport : public OperationSupport
4840 {
4841 public:
4842         WriteSupport (const ResourceDescription& resourceDesc)
4843         {
4844                 DE_ASSERT(isIndirectBuffer(resourceDesc.type));
4845                 DE_UNREF(resourceDesc);
4846         }
4847
4848         deUint32 getInResourceUsageFlags (void) const
4849         {
4850                 return 0;
4851         }
4852
4853         deUint32 getOutResourceUsageFlags (void) const
4854         {
4855                 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4856         }
4857
4858         VkQueueFlags getQueueFlags (const OperationContext& context) const
4859         {
4860                 DE_UNREF(context);
4861                 return VK_QUEUE_TRANSFER_BIT;
4862         }
4863
4864         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
4865         {
4866                 return de::MovePtr<Operation>(new WriteImplementation(context, resource));
4867         }
4868
4869         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
4870         {
4871                 DE_ASSERT(0);
4872                 return de::MovePtr<Operation>();
4873         }
4874 };
4875
4876 } // IndirectBuffer ns
4877
4878 namespace VertexInput
4879 {
4880
4881 enum DrawMode
4882 {
4883         DRAW_MODE_VERTEX        = 0,
4884         DRAW_MODE_INDEXED,
4885 };
4886
4887 class Implementation : public Operation
4888 {
4889 public:
4890         Implementation (OperationContext& context, Resource& resource, DrawMode drawMode)
4891                 : m_context             (context)
4892                 , m_resource    (resource)
4893                 , m_drawMode    (drawMode)
4894         {
4895                 requireFeaturesForSSBOAccess (m_context, VK_SHADER_STAGE_VERTEX_BIT);
4896
4897                 const DeviceInterface&          vk                              = context.getDeviceInterface();
4898                 const VkDevice                          device                  = context.getDevice();
4899                 Allocator&                                      allocator               = context.getAllocator();
4900                 VkFormat                                        attributeFormat = VK_FORMAT_R32G32B32A32_UINT;
4901                 const VkDeviceSize                      dataSizeBytes   = m_resource.getBuffer().size;
4902
4903                 // allocate ssbo that will store data used for verification
4904                 {
4905                         m_outputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4906                                 makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
4907
4908                         const Allocation& alloc = m_outputBuffer->getAllocation();
4909                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(dataSizeBytes));
4910                         flushAlloc(vk, device, alloc);
4911                 }
4912
4913                 // allocate buffer that will be used for vertex attributes when we use resource for indices
4914                 if (m_drawMode == DRAW_MODE_INDEXED)
4915                 {
4916                         attributeFormat = VK_FORMAT_R32_UINT;
4917
4918                         m_inputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
4919                                 makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
4920
4921                         const Allocation& alloc = m_inputBuffer->getAllocation();
4922                         fillPattern(alloc.getHostPtr(), dataSizeBytes, true);
4923                         flushAlloc(vk, device, alloc);
4924                 }
4925
4926                 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
4927                         .addSingleBinding       (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
4928                         .build                          (vk, device);
4929
4930                 m_descriptorPool = DescriptorPoolBuilder()
4931                         .addType        (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4932                         .build          (vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4933
4934                 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
4935
4936                 const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, dataSizeBytes);
4937                 DescriptorSetUpdateBuilder()
4938                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
4939                         .update         (vk, device);
4940
4941                 // Color attachment
4942                 m_colorFormat                                           = VK_FORMAT_R8G8B8A8_UNORM;
4943                 m_colorImageSubresourceRange            = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4944                 m_colorImageExtent                                      = makeExtent3D(16u, 16u, 1u);
4945                 m_colorAttachmentImage                          = de::MovePtr<Image>(new Image(vk, device, allocator,
4946                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4947                                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
4948                         MemoryRequirement::Any));
4949
4950                 // Pipeline
4951                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
4952                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
4953                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height);
4954                 m_pipelineLayout                = makePipelineLayout(vk, device, *m_descriptorSetLayout);
4955
4956                 m_pipeline = GraphicsPipelineBuilder()
4957                         .setPrimitiveTopology                   (VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
4958                         .setRenderSize                                  (tcu::IVec2(static_cast<int>(m_colorImageExtent.width), static_cast<int>(m_colorImageExtent.height)))
4959                         .setVertexInputSingleAttribute  (attributeFormat, tcu::getPixelSize(mapVkFormat(attributeFormat)))
4960                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get("input_vert"), DE_NULL)
4961                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get("input_frag"), DE_NULL)
4962                         .build                                                  (vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
4963         }
4964
4965         void recordCommands (const VkCommandBuffer cmdBuffer)
4966         {
4967                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
4968                 const VkDeviceSize                      dataSizeBytes                   = m_resource.getBuffer().size;
4969                 SynchronizationWrapperPtr       synchronizationWrapper  = getSynchronizationWrapper(m_context.getSynchronizationType(), vk, DE_FALSE);
4970
4971                 // Change color attachment image layout
4972                 {
4973                         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
4974                                 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR,                                // VkPipelineStageFlags2KHR                     srcStageMask
4975                                 (VkAccessFlags)0,                                                                               // VkAccessFlags2KHR                            srcAccessMask
4976                                 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,    // VkPipelineStageFlags2KHR                     dstStageMask
4977                                 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,                             // VkAccessFlags2KHR                            dstAccessMask
4978                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                                        oldLayout
4979                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                               // VkImageLayout                                        newLayout
4980                                 **m_colorAttachmentImage,                                                               // VkImage                                                      image
4981                                 m_colorImageSubresourceRange                                                    // VkImageSubresourceRange                      subresourceRange
4982                         );
4983                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
4984                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
4985                 }
4986
4987                 {
4988                         const VkRect2D  renderArea      = makeRect2D(m_colorImageExtent);
4989                         const tcu::Vec4 clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
4990
4991                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
4992                 }
4993
4994                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4995                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4996
4997                 const VkDeviceSize vertexBufferOffset   = 0ull;
4998                 if (m_drawMode == DRAW_MODE_VERTEX)
4999                 {
5000                         const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(tcu::UVec4));
5001                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_resource.getBuffer().handle, &vertexBufferOffset);
5002                         vk.cmdDraw(cmdBuffer, count, 1u, 0u, 0u);
5003                 }
5004                 else // (m_drawMode == DRAW_MODE_INDEXED)
5005                 {
5006                         const deUint32 count = static_cast<deUint32>(dataSizeBytes / sizeof(deUint32));
5007                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &**m_inputBuffer, &vertexBufferOffset);
5008                         vk.cmdBindIndexBuffer(cmdBuffer, m_resource.getBuffer().handle, 0u, VK_INDEX_TYPE_UINT32);
5009                         vk.cmdDrawIndexed(cmdBuffer, count, 1, 0, 0, 0);
5010                 }
5011
5012                 endRenderPass(vk, cmdBuffer);
5013
5014                 // Insert a barrier so data written by the shader is available to the host
5015                 {
5016                         const VkBufferMemoryBarrier2KHR bufferMemoryBarrier2 = makeBufferMemoryBarrier2(
5017                                 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR,              // VkPipelineStageFlags2KHR                     srcStageMask
5018                                 VK_ACCESS_2_SHADER_WRITE_BIT_KHR,                               // VkAccessFlags2KHR                            srcAccessMask
5019                                 VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                               // VkPipelineStageFlags2KHR                     dstStageMask
5020                                 VK_ACCESS_2_HOST_READ_BIT_KHR,                                  // VkAccessFlags2KHR                            dstAccessMask
5021                                 **m_outputBuffer,                                                               // VkBuffer                                                     buffer
5022                                 0u,                                                                                             // VkDeviceSize                                         offset
5023                                 m_resource.getBuffer().size                                             // VkDeviceSize                                         size
5024                         );
5025                         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, &bufferMemoryBarrier2);
5026                         synchronizationWrapper->cmdPipelineBarrier(cmdBuffer, &dependencyInfo);
5027                 }
5028         }
5029
5030         SyncInfo getInSyncInfo (void) const
5031         {
5032                 const bool                                      usingIndexedDraw        = (m_drawMode == DRAW_MODE_INDEXED);
5033                 VkPipelineStageFlags2KHR        stageMask                       = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5034                 VkAccessFlags2KHR                       accessMask                      = usingIndexedDraw ? VK_ACCESS_2_INDEX_READ_BIT_KHR
5035                                                                                                                                                    : VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR;
5036
5037                 if (m_context.getSynchronizationType() == SynchronizationType::SYNCHRONIZATION2)
5038                 {
5039                         // test new stages added with VK_KHR_synchronization2 (no need to further duplicate those tests);
5040                         // with this operation we can test pre_rasterization, index_input and attribute_input flags;
5041                         // since this operation is executed for three buffers of different size we use diferent flags depending on the size
5042                         if (m_resource.getBuffer().size > MAX_UPDATE_BUFFER_SIZE)
5043                                 stageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR;
5044                         else
5045                                 stageMask = usingIndexedDraw ? VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR
5046                                                                                          : VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR;
5047                 }
5048
5049                 const SyncInfo syncInfo =
5050                 {
5051                         stageMask,                                                                      // VkPipelineStageFlags         stageMask;
5052                         accessMask,                                                                     // VkAccessFlags                        accessMask;
5053                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        imageLayout;
5054                 };
5055                 return syncInfo;
5056         }
5057
5058         SyncInfo getOutSyncInfo (void) const
5059         {
5060                 return emptySyncInfo;
5061         }
5062
5063         Data getData (void) const
5064         {
5065                 return getHostBufferData(m_context, *m_outputBuffer, m_resource.getBuffer().size);
5066         }
5067
5068         void setData (const Data& data)
5069         {
5070                 setHostBufferData(m_context, *m_outputBuffer, data);
5071         }
5072
5073 private:
5074         OperationContext&                       m_context;
5075         Resource&                                       m_resource;
5076         DrawMode                                        m_drawMode;
5077         de::MovePtr<Buffer>                     m_inputBuffer;
5078         de::MovePtr<Buffer>                     m_outputBuffer;
5079         Move<VkRenderPass>                      m_renderPass;
5080         Move<VkFramebuffer>                     m_framebuffer;
5081         Move<VkPipelineLayout>          m_pipelineLayout;
5082         Move<VkPipeline>                        m_pipeline;
5083         VkFormat                                        m_colorFormat;
5084         de::MovePtr<Image>                      m_colorAttachmentImage;
5085         Move<VkImageView>                       m_colorAttachmentView;
5086         VkExtent3D                                      m_colorImageExtent;
5087         VkImageSubresourceRange         m_colorImageSubresourceRange;
5088         Move<VkDescriptorPool>          m_descriptorPool;
5089         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
5090         Move<VkDescriptorSet>           m_descriptorSet;
5091 };
5092
5093 class Support : public OperationSupport
5094 {
5095 public:
5096         Support(const ResourceDescription& resourceDesc, DrawMode drawMode)
5097                 : m_resourceDesc        (resourceDesc)
5098                 , m_drawMode            (drawMode)
5099         {
5100                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER || m_resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER);
5101         }
5102
5103         void initPrograms (SourceCollections& programCollection) const
5104         {
5105                 // Vertex
5106                 {
5107                         std::ostringstream src;
5108                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n";
5109                         if (m_drawMode == DRAW_MODE_VERTEX)
5110                         {
5111                                 src << "layout(location = 0) in uvec4 v_in_data;\n"
5112                                         << "layout(set = 0, binding = 0, std140) writeonly buffer Output {\n"
5113                                         << "    uvec4 data[" << m_resourceDesc.size.x() / sizeof(tcu::UVec4) << "];\n"
5114                                         << "} b_out;\n"
5115                                         << "\n"
5116                                         << "void main (void)\n"
5117                                         << "{\n"
5118                                         << "    b_out.data[gl_VertexIndex] = v_in_data;\n"
5119                                         << "    gl_PointSize = 1.0f;\n"
5120                                         << "}\n";
5121                         }
5122                         else // DRAW_MODE_INDEXED
5123                         {
5124                                 src << "layout(location = 0) in uint v_in_data;\n"
5125                                         << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
5126                                         << "    uint data[" << m_resourceDesc.size.x() / sizeof(deUint32) << "];\n"
5127                                         << "} b_out;\n"
5128                                         << "\n"
5129                                         << "void main (void)\n"
5130                                         << "{\n"
5131                                         << "    b_out.data[gl_VertexIndex] = v_in_data;\n"
5132                                         << "    gl_PointSize = 1.0f;\n"
5133                                         << "}\n";
5134                         }
5135                         programCollection.glslSources.add("input_vert") << glu::VertexSource(src.str());
5136                 }
5137
5138                 // Fragment
5139                 {
5140                         std::ostringstream src;
5141                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
5142                                 << "\n"
5143                                 << "layout(location = 0) out vec4 o_color;\n"
5144                                 << "\n"
5145                                 << "void main (void)\n"
5146                                 << "{\n"
5147                                 << "    o_color = vec4(1.0);\n"
5148                                 << "}\n";
5149                         programCollection.glslSources.add("input_frag") << glu::FragmentSource(src.str());
5150                 }
5151         }
5152
5153         deUint32 getInResourceUsageFlags (void) const
5154         {
5155                 return (m_drawMode == DRAW_MODE_VERTEX) ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT : VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
5156         }
5157
5158         deUint32 getOutResourceUsageFlags (void) const
5159         {
5160                 return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
5161         }
5162
5163         VkQueueFlags getQueueFlags (const OperationContext&) const
5164         {
5165                 return VK_QUEUE_GRAPHICS_BIT;
5166         }
5167
5168         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
5169         {
5170                 return de::MovePtr<Operation>(new Implementation(context, resource, m_drawMode));
5171         }
5172
5173         de::MovePtr<Operation> build (OperationContext&, Resource&, Resource&) const
5174         {
5175                 DE_ASSERT(0);
5176                 return de::MovePtr<Operation>();
5177         }
5178
5179 private:
5180         const ResourceDescription       m_resourceDesc;
5181         const DrawMode                          m_drawMode;
5182 };
5183
5184 } // VertexInput
5185
5186 } // anonymous ns
5187
5188 OperationContext::OperationContext (Context& context, SynchronizationType syncType, PipelineCacheData& pipelineCacheData)
5189         : m_context                             (context)
5190         , m_syncType                    (syncType)
5191         , m_vki                                 (context.getInstanceInterface())
5192         , m_vk                                  (context.getDeviceInterface())
5193         , m_physicalDevice              (context.getPhysicalDevice())
5194         , m_device                              (context.getDevice())
5195         , m_allocator                   (context.getDefaultAllocator())
5196         , m_progCollection              (context.getBinaryCollection())
5197         , m_pipelineCacheData   (pipelineCacheData)
5198 {
5199 }
5200
5201 OperationContext::OperationContext (Context&                            context,
5202                                                                         SynchronizationType             syncType,
5203                                                                         const DeviceInterface&  vk,
5204                                                                         const VkDevice                  device,
5205                                                                         vk::Allocator&                  allocator,
5206                                                                         PipelineCacheData&              pipelineCacheData)
5207         : m_context                             (context)
5208         , m_syncType                    (syncType)
5209         , m_vki                                 (context.getInstanceInterface())
5210         , m_vk                                  (vk)
5211         , m_physicalDevice              (context.getPhysicalDevice())
5212         , m_device                              (device)
5213         , m_allocator                   (allocator)
5214         , m_progCollection              (context.getBinaryCollection())
5215         , m_pipelineCacheData   (pipelineCacheData)
5216 {
5217 }
5218
5219 OperationContext::OperationContext (Context&                                            context,
5220                                                                         SynchronizationType                             syncType,
5221                                                                         const vk::InstanceInterface&    vki,
5222                                                                         const vk::DeviceInterface&              vkd,
5223                                                                         vk::VkPhysicalDevice                    physicalDevice,
5224                                                                         vk::VkDevice                                    device,
5225                                                                         vk::Allocator&                                  allocator,
5226                                                                         vk::BinaryCollection&                   programCollection,
5227                                                                         PipelineCacheData&                              pipelineCacheData)
5228         : m_context                             (context)
5229         , m_syncType                    (syncType)
5230         , m_vki                                 (vki)
5231         , m_vk                                  (vkd)
5232         , m_physicalDevice              (physicalDevice)
5233         , m_device                              (device)
5234         , m_allocator                   (allocator)
5235         , m_progCollection              (programCollection)
5236         , m_pipelineCacheData   (pipelineCacheData)
5237 {
5238 }
5239
5240 Resource::Resource (OperationContext& context, const ResourceDescription& desc, const deUint32 usage, const vk::VkSharingMode sharingMode, const std::vector<deUint32>& queueFamilyIndex)
5241         : m_type        (desc.type)
5242 {
5243         const DeviceInterface&          vk                      = context.getDeviceInterface();
5244         const InstanceInterface&        vki                     = context.getInstanceInterface();
5245         const VkDevice                          device          = context.getDevice();
5246         const VkPhysicalDevice          physDevice      = context.getPhysicalDevice();
5247         Allocator&                                      allocator       = context.getAllocator();
5248
5249         if (m_type == RESOURCE_TYPE_BUFFER || m_type == RESOURCE_TYPE_INDEX_BUFFER || isIndirectBuffer(m_type))
5250         {
5251                 m_bufferData = de::MovePtr<BufferResource>(new BufferResource(DE_NULL, 0u, static_cast<VkDeviceSize>(desc.size.x())));
5252                 VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData->size, usage);
5253                 bufferCreateInfo.sharingMode            = sharingMode;
5254                 if (queueFamilyIndex.size() > 0)
5255                 {
5256                         bufferCreateInfo.queueFamilyIndexCount  = static_cast<deUint32>(queueFamilyIndex.size());
5257                         bufferCreateInfo.pQueueFamilyIndices    = &queueFamilyIndex[0];
5258                 }
5259                 m_buffer                                = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
5260                 m_bufferData->handle    = **m_buffer;
5261         }
5262         else if (m_type == RESOURCE_TYPE_IMAGE)
5263         {
5264                 m_imageData = de::MovePtr<ImageResource>(new ImageResource(
5265                         DE_NULL,
5266                         makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z())),
5267                         desc.imageType,
5268                         desc.imageFormat,
5269                         makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u),
5270                         makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u),
5271                         vk::VK_IMAGE_TILING_OPTIMAL
5272                 ));
5273                 VkImageCreateInfo imageInfo             = makeImageCreateInfo(m_imageData->imageType, m_imageData->extent, m_imageData->format, usage, desc.imageSamples, m_imageData->tiling);
5274                 imageInfo.sharingMode                   = sharingMode;
5275                 if (queueFamilyIndex.size() > 0)
5276                 {
5277                         imageInfo.queueFamilyIndexCount = static_cast<deUint32>(queueFamilyIndex.size());
5278                         imageInfo.pQueueFamilyIndices   = &queueFamilyIndex[0];
5279                 }
5280
5281                 VkImageFormatProperties imageFormatProperties;
5282                 const VkResult formatResult             = vki.getPhysicalDeviceImageFormatProperties(physDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProperties);
5283
5284                 if (formatResult != VK_SUCCESS)
5285                         TCU_THROW(NotSupportedError, "Image format is not supported");
5286
5287                 if ((imageFormatProperties.sampleCounts & desc.imageSamples) != desc.imageSamples)
5288                         TCU_THROW(NotSupportedError, "Requested sample count is not supported");
5289
5290                 m_image                                                 = de::MovePtr<Image>(new Image(vk, device, allocator, imageInfo, MemoryRequirement::Any));
5291                 m_imageData->handle                             = **m_image;
5292         }
5293         else
5294                 DE_ASSERT(0);
5295 }
5296
5297 Resource::Resource (ResourceType                                type,
5298                                         vk::Move<vk::VkBuffer>          buffer,
5299                                         de::MovePtr<vk::Allocation>     allocation,
5300                                         vk::VkDeviceSize                        offset,
5301                                         vk::VkDeviceSize                        size)
5302         : m_type                (type)
5303         , m_buffer              (new Buffer(buffer, allocation))
5304         , m_bufferData  (de::MovePtr<BufferResource>(new BufferResource(m_buffer->get(), offset, size)))
5305 {
5306         DE_ASSERT(type != RESOURCE_TYPE_IMAGE);
5307 }
5308
5309 Resource::Resource (vk::Move<vk::VkImage>                       image,
5310                                         de::MovePtr<vk::Allocation>             allocation,
5311                                         const vk::VkExtent3D&                   extent,
5312                                         vk::VkImageType                                 imageType,
5313                                         vk::VkFormat                                    format,
5314                                         vk::VkImageSubresourceRange             subresourceRange,
5315                                         vk::VkImageSubresourceLayers    subresourceLayers,
5316                                         vk::VkImageTiling                               tiling)
5317         : m_type                (RESOURCE_TYPE_IMAGE)
5318         , m_image               (new Image(image, allocation))
5319         , m_imageData   (de::MovePtr<ImageResource>(new ImageResource(m_image->get(), extent, imageType, format, subresourceRange, subresourceLayers, tiling)))
5320 {
5321 }
5322
5323 vk::VkDeviceMemory Resource::getMemory (void) const
5324 {
5325         if (m_type == RESOURCE_TYPE_IMAGE)
5326                 return m_image->getAllocation().getMemory();
5327         else
5328                 return m_buffer->getAllocation().getMemory();
5329 }
5330
5331 //! \note This function exists for performance reasons. We're creating a lot of tests and checking requirements here
5332 //!       before creating an OperationSupport object is faster.
5333 bool isResourceSupported (const OperationName opName, const ResourceDescription& resourceDesc)
5334 {
5335         switch (opName)
5336         {
5337                 case OPERATION_NAME_WRITE_FILL_BUFFER:
5338                 case OPERATION_NAME_WRITE_COPY_BUFFER:
5339                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:
5340                 case OPERATION_NAME_WRITE_SSBO_VERTEX:
5341                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:
5342                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:
5343                 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:
5344                 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:
5345                 case OPERATION_NAME_WRITE_SSBO_COMPUTE:
5346                 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:
5347                 case OPERATION_NAME_READ_COPY_BUFFER:
5348                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:
5349                 case OPERATION_NAME_READ_SSBO_VERTEX:
5350                 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:
5351                 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:
5352                 case OPERATION_NAME_READ_SSBO_GEOMETRY:
5353                 case OPERATION_NAME_READ_SSBO_FRAGMENT:
5354                 case OPERATION_NAME_READ_SSBO_COMPUTE:
5355                 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:
5356                 case OPERATION_NAME_READ_VERTEX_INPUT:
5357                         return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5358
5359                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:
5360                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:
5361                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW;
5362
5363                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:
5364                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:
5365                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED;
5366
5367                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:
5368                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:
5369                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH;
5370
5371                 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:
5372                 case OPERATION_NAME_READ_INDEX_INPUT:
5373                         return resourceDesc.type == RESOURCE_TYPE_INDEX_BUFFER;
5374
5375                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:
5376                         return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UPDATE_BUFFER_SIZE;
5377
5378                 case OPERATION_NAME_WRITE_COPY_IMAGE:
5379                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:
5380                 case OPERATION_NAME_READ_COPY_IMAGE:
5381                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:
5382                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5383
5384                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:
5385                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType != VK_IMAGE_TYPE_3D
5386                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5387
5388                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:
5389                 case OPERATION_NAME_READ_RESOLVE_IMAGE:
5390                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5391                                 && resourceDesc.imageSamples != VK_SAMPLE_COUNT_1_BIT;
5392
5393                 case OPERATION_NAME_WRITE_BLIT_IMAGE:
5394                 case OPERATION_NAME_READ_BLIT_IMAGE:
5395                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:
5396                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:
5397                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:
5398                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:
5399                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:
5400                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:
5401                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:
5402                 case OPERATION_NAME_READ_IMAGE_VERTEX:
5403                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:
5404                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:
5405                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:
5406                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:
5407                 case OPERATION_NAME_READ_IMAGE_COMPUTE:
5408                 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:
5409                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5410                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5411
5412                 case OPERATION_NAME_READ_UBO_VERTEX:
5413                 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:
5414                 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:
5415                 case OPERATION_NAME_READ_UBO_GEOMETRY:
5416                 case OPERATION_NAME_READ_UBO_FRAGMENT:
5417                 case OPERATION_NAME_READ_UBO_COMPUTE:
5418                 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:
5419                         return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UBO_RANGE;
5420
5421                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:
5422                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5423                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5424
5425                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:
5426                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
5427                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5428
5429                 case OPERATION_NAME_WRITE_DRAW:
5430                 case OPERATION_NAME_WRITE_DRAW_INDEXED:
5431                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:
5432                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:
5433                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType == VK_IMAGE_TYPE_2D
5434                                 && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0
5435                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5436
5437                 case OPERATION_NAME_COPY_BUFFER:
5438                 case OPERATION_NAME_COPY_SSBO_VERTEX:
5439                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:
5440                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:
5441                 case OPERATION_NAME_COPY_SSBO_GEOMETRY:
5442                 case OPERATION_NAME_COPY_SSBO_FRAGMENT:
5443                 case OPERATION_NAME_COPY_SSBO_COMPUTE:
5444                 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:
5445                         return resourceDesc.type == RESOURCE_TYPE_BUFFER;
5446
5447                 case OPERATION_NAME_COPY_IMAGE:
5448                 case OPERATION_NAME_BLIT_IMAGE:
5449                 case OPERATION_NAME_COPY_IMAGE_VERTEX:
5450                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:
5451                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:
5452                 case OPERATION_NAME_COPY_IMAGE_GEOMETRY:
5453                 case OPERATION_NAME_COPY_IMAGE_FRAGMENT:
5454                 case OPERATION_NAME_COPY_IMAGE_COMPUTE:
5455                 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:
5456                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT
5457                                 && resourceDesc.imageSamples == VK_SAMPLE_COUNT_1_BIT;
5458
5459                 default:
5460                         DE_ASSERT(0);
5461                         return false;
5462         }
5463 }
5464
5465 std::string getOperationName (const OperationName opName)
5466 {
5467         switch (opName)
5468         {
5469                 case OPERATION_NAME_WRITE_FILL_BUFFER:                                          return "write_fill_buffer";
5470                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:                                        return "write_update_buffer";
5471                 case OPERATION_NAME_WRITE_COPY_BUFFER:                                          return "write_copy_buffer";
5472                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:                         return "write_copy_buffer_to_image";
5473                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:                         return "write_copy_image_to_buffer";
5474                 case OPERATION_NAME_WRITE_COPY_IMAGE:                                           return "write_copy_image";
5475                 case OPERATION_NAME_WRITE_BLIT_IMAGE:                                           return "write_blit_image";
5476                 case OPERATION_NAME_WRITE_SSBO_VERTEX:                                          return "write_ssbo_vertex";
5477                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:            return "write_ssbo_tess_control";
5478                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:         return "write_ssbo_tess_eval";
5479                 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:                                        return "write_ssbo_geometry";
5480                 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:                                        return "write_ssbo_fragment";
5481                 case OPERATION_NAME_WRITE_SSBO_COMPUTE:                                         return "write_ssbo_compute";
5482                 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:                        return "write_ssbo_compute_indirect";
5483                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:                                         return "write_image_vertex";
5484                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:           return "write_image_tess_control";
5485                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:        return "write_image_tess_eval";
5486                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:                                       return "write_image_geometry";
5487                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:                                       return "write_image_fragment";
5488                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:                                        return "write_image_compute";
5489                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:            return "write_image_compute_multisample";
5490                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:                       return "write_image_compute_indirect";
5491                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:                            return "write_clear_color_image";
5492                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:            return "write_clear_depth_stencil_image";
5493                 case OPERATION_NAME_WRITE_DRAW:                                                         return "write_draw";
5494                 case OPERATION_NAME_WRITE_DRAW_INDEXED:                                         return "write_draw_indexed";
5495                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:                                        return "write_draw_indirect";
5496                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:                        return "write_draw_indexed_indirect";
5497                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:                            return "write_clear_attachments";
5498                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:                         return "write_indirect_buffer_draw";
5499                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:         return "write_indirect_buffer_draw_indexed";
5500                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:                     return "write_indirect_buffer_dispatch";
5501                 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:                          return "write_update_index_buffer";
5502
5503                 case OPERATION_NAME_READ_COPY_BUFFER:                                           return "read_copy_buffer";
5504                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:                          return "read_copy_buffer_to_image";
5505                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:                          return "read_copy_image_to_buffer";
5506                 case OPERATION_NAME_READ_COPY_IMAGE:                                            return "read_copy_image";
5507                 case OPERATION_NAME_READ_BLIT_IMAGE:                                            return "read_blit_image";
5508                 case OPERATION_NAME_READ_RESOLVE_IMAGE:                                         return "read_resolve_image";
5509                 case OPERATION_NAME_READ_UBO_VERTEX:                                            return "read_ubo_vertex";
5510                 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:                      return "read_ubo_tess_control";
5511                 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:           return "read_ubo_tess_eval";
5512                 case OPERATION_NAME_READ_UBO_GEOMETRY:                                          return "read_ubo_geometry";
5513                 case OPERATION_NAME_READ_UBO_FRAGMENT:                                          return "read_ubo_fragment";
5514                 case OPERATION_NAME_READ_UBO_COMPUTE:                                           return "read_ubo_compute";
5515                 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:                          return "read_ubo_compute_indirect";
5516                 case OPERATION_NAME_READ_SSBO_VERTEX:                                           return "read_ssbo_vertex";
5517                 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:                     return "read_ssbo_tess_control";
5518                 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:          return "read_ssbo_tess_eval";
5519                 case OPERATION_NAME_READ_SSBO_GEOMETRY:                                         return "read_ssbo_geometry";
5520                 case OPERATION_NAME_READ_SSBO_FRAGMENT:                                         return "read_ssbo_fragment";
5521                 case OPERATION_NAME_READ_SSBO_COMPUTE:                                          return "read_ssbo_compute";
5522                 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:                         return "read_ssbo_compute_indirect";
5523                 case OPERATION_NAME_READ_IMAGE_VERTEX:                                          return "read_image_vertex";
5524                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:            return "read_image_tess_control";
5525                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:         return "read_image_tess_eval";
5526                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:                                        return "read_image_geometry";
5527                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:                                        return "read_image_fragment";
5528                 case OPERATION_NAME_READ_IMAGE_COMPUTE:                                         return "read_image_compute";
5529                 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:                        return "read_image_compute_indirect";
5530                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:                          return "read_indirect_buffer_draw";
5531                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:          return "read_indirect_buffer_draw_indexed";
5532                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:                      return "read_indirect_buffer_dispatch";
5533                 case OPERATION_NAME_READ_VERTEX_INPUT:                                          return "read_vertex_input";
5534                 case OPERATION_NAME_READ_INDEX_INPUT:                                           return "read_index_input";
5535
5536                 case OPERATION_NAME_COPY_BUFFER:                                                        return "copy_buffer";
5537                 case OPERATION_NAME_COPY_IMAGE:                                                         return "copy_image";
5538                 case OPERATION_NAME_BLIT_IMAGE:                                                         return "blit_image";
5539                 case OPERATION_NAME_COPY_SSBO_VERTEX:                                           return "copy_buffer_vertex";
5540                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:                     return "copy_ssbo_tess_control";
5541                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:          return "copy_ssbo_tess_eval";
5542                 case OPERATION_NAME_COPY_SSBO_GEOMETRY:                                         return "copy_ssbo_geometry";
5543                 case OPERATION_NAME_COPY_SSBO_FRAGMENT:                                         return "copy_ssbo_fragment";
5544                 case OPERATION_NAME_COPY_SSBO_COMPUTE:                                          return "copy_ssbo_compute";
5545                 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:                         return "copy_ssbo_compute_indirect";
5546                 case OPERATION_NAME_COPY_IMAGE_VERTEX:                                          return "copy_image_vertex";
5547                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:            return "copy_image_tess_control";
5548                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:         return "copy_image_tess_eval";
5549                 case OPERATION_NAME_COPY_IMAGE_GEOMETRY:                                        return "copy_image_geometry";
5550                 case OPERATION_NAME_COPY_IMAGE_FRAGMENT:                                        return "copy_image_fragment";
5551                 case OPERATION_NAME_COPY_IMAGE_COMPUTE:                                         return "copy_image_compute";
5552                 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:                        return "copy_image_compute_indirect";
5553                 default:
5554                         DE_ASSERT(0);
5555                         return "";
5556         }
5557 }
5558
5559 de::MovePtr<OperationSupport> makeOperationSupport (const OperationName opName, const ResourceDescription& resourceDesc)
5560 {
5561         switch (opName)
5562         {
5563                 case OPERATION_NAME_WRITE_FILL_BUFFER:                                          return de::MovePtr<OperationSupport>(new FillUpdateBuffer       ::Support               (resourceDesc, FillUpdateBuffer::BUFFER_OP_FILL));
5564                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:                                        return de::MovePtr<OperationSupport>(new FillUpdateBuffer       ::Support               (resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE));
5565                 case OPERATION_NAME_WRITE_COPY_BUFFER:                                          return de::MovePtr<OperationSupport>(new CopyBuffer                     ::Support               (resourceDesc, ACCESS_MODE_WRITE));
5566                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:                         return de::MovePtr<OperationSupport>(new CopyBufferToImage      ::Support               (resourceDesc, ACCESS_MODE_WRITE));
5567                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:                         return de::MovePtr<OperationSupport>(new CopyImageToBuffer      ::Support               (resourceDesc, ACCESS_MODE_WRITE));
5568                 case OPERATION_NAME_WRITE_COPY_IMAGE:                                           return de::MovePtr<OperationSupport>(new CopyBlitResolveImage   ::Support       (resourceDesc, CopyBlitResolveImage::TYPE_COPY, ACCESS_MODE_WRITE));
5569                 case OPERATION_NAME_WRITE_BLIT_IMAGE:                                           return de::MovePtr<OperationSupport>(new CopyBlitResolveImage   ::Support       (resourceDesc, CopyBlitResolveImage::TYPE_BLIT, ACCESS_MODE_WRITE));
5570                 case OPERATION_NAME_WRITE_SSBO_VERTEX:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5571                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:            return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5572                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:         return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5573                 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5574                 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5575                 case OPERATION_NAME_WRITE_SSBO_COMPUTE:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5576                 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5577                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
5578                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:           return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5579                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5580                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:                                       return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
5581                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:                                       return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
5582                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
5583                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:                       return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5584                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_MULTISAMPLE:            return de::MovePtr<OperationSupport>(new ShaderAccess           ::MSImageSupport(resourceDesc));
5585                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:                            return de::MovePtr<OperationSupport>(new ClearImage                     ::Support               (resourceDesc, ClearImage::CLEAR_MODE_COLOR));
5586                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:            return de::MovePtr<OperationSupport>(new ClearImage                     ::Support               (resourceDesc, ClearImage::CLEAR_MODE_DEPTH_STENCIL));
5587                 case OPERATION_NAME_WRITE_DRAW:                                                         return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW));
5588                 case OPERATION_NAME_WRITE_DRAW_INDEXED:                                         return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED));
5589                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:                                        return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDIRECT));
5590                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:                        return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED_INDIRECT));
5591                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:                            return de::MovePtr<OperationSupport>(new ClearAttachments       ::Support               (resourceDesc));
5592                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:                         return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
5593                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:         return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
5594                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:                     return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
5595                 case OPERATION_NAME_WRITE_UPDATE_INDEX_BUFFER:                          return de::MovePtr<OperationSupport>(new FillUpdateBuffer       ::Support               (resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE_WITH_INDEX_PATTERN));
5596
5597                 case OPERATION_NAME_READ_COPY_BUFFER:                                           return de::MovePtr<OperationSupport>(new CopyBuffer                     ::Support               (resourceDesc, ACCESS_MODE_READ));
5598                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:                          return de::MovePtr<OperationSupport>(new CopyBufferToImage      ::Support               (resourceDesc, ACCESS_MODE_READ));
5599                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:                          return de::MovePtr<OperationSupport>(new CopyImageToBuffer      ::Support               (resourceDesc, ACCESS_MODE_READ));
5600                 case OPERATION_NAME_READ_COPY_IMAGE:                                            return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support          (resourceDesc, CopyBlitResolveImage::TYPE_COPY,         ACCESS_MODE_READ));
5601                 case OPERATION_NAME_READ_BLIT_IMAGE:                                            return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support          (resourceDesc, CopyBlitResolveImage::TYPE_BLIT,         ACCESS_MODE_READ));
5602                 case OPERATION_NAME_READ_RESOLVE_IMAGE:                                         return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::Support          (resourceDesc, CopyBlitResolveImage::TYPE_RESOLVE,      ACCESS_MODE_READ));
5603                 case OPERATION_NAME_READ_UBO_VERTEX:                                            return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5604                 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:                      return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5605                 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:           return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5606                 case OPERATION_NAME_READ_UBO_GEOMETRY:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5607                 case OPERATION_NAME_READ_UBO_FRAGMENT:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5608                 case OPERATION_NAME_READ_UBO_COMPUTE:                                           return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5609                 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_UNIFORM, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5610                 case OPERATION_NAME_READ_SSBO_VERTEX:                                           return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5611                 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:                     return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5612                 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5613                 case OPERATION_NAME_READ_SSBO_GEOMETRY:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5614                 case OPERATION_NAME_READ_SSBO_FRAGMENT:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5615                 case OPERATION_NAME_READ_SSBO_COMPUTE:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5616                 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::BufferSupport (resourceDesc, BUFFER_TYPE_STORAGE, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5617                 case OPERATION_NAME_READ_IMAGE_VERTEX:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
5618                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:            return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5619                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5620                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
5621                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
5622                 case OPERATION_NAME_READ_IMAGE_COMPUTE:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
5623                 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5624                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:                          return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
5625                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:          return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
5626                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:                      return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
5627                 case OPERATION_NAME_READ_VERTEX_INPUT:                                          return de::MovePtr<OperationSupport>(new VertexInput            ::Support               (resourceDesc, VertexInput::DRAW_MODE_VERTEX));
5628                 case OPERATION_NAME_READ_INDEX_INPUT:                                           return de::MovePtr<OperationSupport>(new VertexInput            ::Support               (resourceDesc, VertexInput::DRAW_MODE_INDEXED));
5629
5630                 case OPERATION_NAME_COPY_BUFFER:                                                        return de::MovePtr<OperationSupport>(new CopyBuffer                     ::CopySupport           (resourceDesc));
5631                 case OPERATION_NAME_COPY_IMAGE:                                                         return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport              (resourceDesc, CopyBlitResolveImage::TYPE_COPY));
5632                 case OPERATION_NAME_BLIT_IMAGE:                                                         return de::MovePtr<OperationSupport>(new CopyBlitResolveImage::CopySupport              (resourceDesc, CopyBlitResolveImage::TYPE_BLIT));
5633                 case OPERATION_NAME_COPY_SSBO_VERTEX:                                           return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_VERTEX_BIT));
5634                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_CONTROL:                     return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5635                 case OPERATION_NAME_COPY_SSBO_TESSELLATION_EVALUATION:          return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5636                 case OPERATION_NAME_COPY_SSBO_GEOMETRY:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_GEOMETRY_BIT));
5637                 case OPERATION_NAME_COPY_SSBO_FRAGMENT:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_FRAGMENT_BIT));
5638                 case OPERATION_NAME_COPY_SSBO_COMPUTE:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT));
5639                 case OPERATION_NAME_COPY_SSBO_COMPUTE_INDIRECT:                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyBufferSupport     (resourceDesc, BUFFER_TYPE_STORAGE, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5640                 case OPERATION_NAME_COPY_IMAGE_VERTEX:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_VERTEX_BIT));
5641                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_CONTROL:            return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
5642                 case OPERATION_NAME_COPY_IMAGE_TESSELLATION_EVALUATION:         return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
5643                 case OPERATION_NAME_COPY_IMAGE_GEOMETRY:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_GEOMETRY_BIT));
5644                 case OPERATION_NAME_COPY_IMAGE_FRAGMENT:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_FRAGMENT_BIT));
5645                 case OPERATION_NAME_COPY_IMAGE_COMPUTE:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT));
5646                 case OPERATION_NAME_COPY_IMAGE_COMPUTE_INDIRECT:                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::CopyImageSupport      (resourceDesc, VK_SHADER_STAGE_COMPUTE_BIT, ShaderAccess::DISPATCH_CALL_DISPATCH_INDIRECT));
5647
5648                 default:
5649                         DE_ASSERT(0);
5650                         return de::MovePtr<OperationSupport>();
5651         }
5652 }
5653
5654 } // synchronization
5655 } // vkt