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