Add missing barrier in synchronization tests
[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 "vkQueryUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "deUniquePtr.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include <vector>
39 #include <sstream>
40
41 namespace vkt
42 {
43 namespace synchronization
44 {
45 namespace
46 {
47 using namespace vk;
48
49 enum Constants
50 {
51         MAX_IMAGE_DIMENSION_2D  = 0x1000u,
52         MAX_UBO_RANGE                   = 0x4000u,
53         MAX_UPDATE_BUFFER_SIZE  = 0x10000u,
54 };
55
56 enum BufferType
57 {
58         BUFFER_TYPE_UNIFORM,
59         BUFFER_TYPE_STORAGE,
60 };
61
62 enum AccessMode
63 {
64         ACCESS_MODE_READ,
65         ACCESS_MODE_WRITE,
66 };
67
68 enum PipelineType
69 {
70         PIPELINE_TYPE_GRAPHICS,
71         PIPELINE_TYPE_COMPUTE,
72 };
73
74 static const char* const s_perVertexBlock =     "gl_PerVertex {\n"
75                                                                                         "    vec4 gl_Position;\n"
76                                                                                         "}";
77
78 //! A pipeline that can be embedded inside an operation.
79 class Pipeline
80 {
81 public:
82         virtual                 ~Pipeline               (void) {}
83         virtual void    recordCommands  (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet) = 0;
84 };
85
86 //! Vertex data that covers the whole viewport with two triangles.
87 class VertexGrid
88 {
89 public:
90         VertexGrid (OperationContext& context)
91         {
92                 const DeviceInterface&  vk                      = context.getDeviceInterface();
93                 const VkDevice                  device          = context.getDevice();
94                 Allocator&                              allocator       = context.getAllocator();
95
96                 // Vertex positions
97                 {
98                         m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
99                         m_vertexData.push_back(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
100                         m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
101
102                         m_vertexData.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
103                         m_vertexData.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
104                         m_vertexData.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
105                 }
106                 m_vertexFormat                                                  = VK_FORMAT_R32G32B32A32_SFLOAT;
107                 m_vertexStride                                                  = tcu::getPixelSize(mapVkFormat(m_vertexFormat));
108                 const VkDeviceSize vertexDataSizeBytes  = m_vertexData.size() * sizeof(m_vertexData[0]);
109
110                 m_vertexBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
111                         makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
112
113                 DE_ASSERT(sizeof(m_vertexData[0]) == m_vertexStride);
114
115                 {
116                         const Allocation& alloc = m_vertexBuffer->getAllocation();
117                         deMemcpy(alloc.getHostPtr(), &m_vertexData[0], static_cast<std::size_t>(vertexDataSizeBytes));
118                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes);
119                 }
120
121                 // Indices
122                 {
123                         const VkDeviceSize indexBufferSizeBytes = sizeof(deUint32) * m_vertexData.size();
124                         const deUint32 numIndices                                       = static_cast<deUint32>(m_vertexData.size());
125                         m_indexBuffer                                                   = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
126                                 makeBufferCreateInfo(indexBufferSizeBytes, VK_BUFFER_USAGE_INDEX_BUFFER_BIT), MemoryRequirement::HostVisible));
127
128                         const Allocation&       alloc   = m_indexBuffer->getAllocation();
129                         deUint32* const         pData   = static_cast<deUint32*>(alloc.getHostPtr());
130
131                         for (deUint32 i = 0; i < numIndices; ++i)
132                                 pData[i] = i;
133
134                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), indexBufferSizeBytes);
135                 }
136         }
137
138         VkFormat        getVertexFormat         (void) const { return m_vertexFormat; }
139         deUint32        getVertexStride         (void) const { return m_vertexStride; }
140         VkIndexType getIndexType                (void) const { return VK_INDEX_TYPE_UINT32; }
141         deUint32        getNumVertices          (void) const { return static_cast<deUint32>(m_vertexData.size()); }
142         deUint32        getNumIndices           (void) const { return getNumVertices(); }
143         VkBuffer        getVertexBuffer         (void) const { return **m_vertexBuffer; }
144         VkBuffer        getIndexBuffer          (void) const { return **m_indexBuffer; }
145
146 private:
147         VkFormat                                        m_vertexFormat;
148         deUint32                                        m_vertexStride;
149         std::vector<tcu::Vec4>          m_vertexData;
150         de::MovePtr<Buffer>                     m_vertexBuffer;
151         de::MovePtr<Buffer>                     m_indexBuffer;
152 };
153
154 //! Add flags for all shader stages required to support a particular stage (e.g. fragment requires vertex as well).
155 VkShaderStageFlags getRequiredStages (const VkShaderStageFlagBits stage)
156 {
157         if (stage & VK_SHADER_STAGE_COMPUTE_BIT)
158         {
159                 DE_ASSERT(stage == VK_SHADER_STAGE_COMPUTE_BIT);
160                 return stage;
161         }
162         else
163                 DE_ASSERT((stage & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
164
165         VkShaderStageFlags flags = 0u;
166
167         if (stage & VK_SHADER_STAGE_ALL_GRAPHICS)
168                 flags |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
169         if (stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
170                 flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
171         if (stage & VK_SHADER_STAGE_GEOMETRY_BIT)
172                 flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
173
174         return flags;
175 }
176
177 //! Check that SSBO read/write is available and that all shader stages are supported.
178 void requireFeaturesForSSBOAccess (OperationContext& context, const VkShaderStageFlags usedStages)
179 {
180         const InstanceInterface&        vki                     = context.getInstanceInterface();
181         const VkPhysicalDevice          physDevice      = context.getPhysicalDevice();
182         FeatureFlags                            flags           = (FeatureFlags)0;
183
184         if (usedStages & VK_SHADER_STAGE_FRAGMENT_BIT)
185                 flags |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
186         if (usedStages & (VK_SHADER_STAGE_ALL_GRAPHICS & (~VK_SHADER_STAGE_FRAGMENT_BIT)))
187                 flags |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
188         if (usedStages & VK_SHADER_STAGE_GEOMETRY_BIT)
189                 flags |= FEATURE_GEOMETRY_SHADER;
190         if (usedStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
191                 flags |= FEATURE_TESSELLATION_SHADER;
192
193         requireFeatures(vki, physDevice, flags);
194 }
195
196 Data getHostBufferData (const OperationContext& context, const Buffer& hostBuffer, const VkDeviceSize size)
197 {
198         const DeviceInterface&  vk              = context.getDeviceInterface();
199         const VkDevice                  device  = context.getDevice();
200         const Allocation&               alloc   = hostBuffer.getAllocation();
201
202         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size);
203
204         const Data data =
205         {
206                 static_cast<std::size_t>(size),                                 // std::size_t          size;
207                 static_cast<deUint8*>(alloc.getHostPtr()),              // const deUint8*       data;
208         };
209         return data;
210 }
211
212 void assertValidShaderStage (const VkShaderStageFlagBits stage)
213 {
214         switch (stage)
215         {
216                 case VK_SHADER_STAGE_VERTEX_BIT:
217                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
218                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
219                 case VK_SHADER_STAGE_GEOMETRY_BIT:
220                 case VK_SHADER_STAGE_FRAGMENT_BIT:
221                 case VK_SHADER_STAGE_COMPUTE_BIT:
222                         // OK
223                         break;
224
225                 default:
226                         DE_ASSERT(0);
227                         break;
228         }
229 }
230
231 VkPipelineStageFlags pipelineStageFlagsFromShaderStageFlagBits (const VkShaderStageFlagBits shaderStage)
232 {
233         switch (shaderStage)
234         {
235                 case VK_SHADER_STAGE_VERTEX_BIT:                                        return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
236                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:          return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
237                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:       return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
238                 case VK_SHADER_STAGE_GEOMETRY_BIT:                                      return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
239                 case VK_SHADER_STAGE_FRAGMENT_BIT:                                      return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
240                 case VK_SHADER_STAGE_COMPUTE_BIT:                                       return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
241
242                 // Other usages are probably an error, so flag that.
243                 default:
244                         DE_ASSERT(0);
245                         return (VkPipelineStageFlags)0;
246         }
247 }
248
249 //! Fill destination buffer with a repeating pattern.
250 void fillPattern (void* const pData, const VkDeviceSize size)
251 {
252         static const deUint8 pattern[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
253         deUint8* const           pBytes    = static_cast<deUint8*>(pData);
254
255         for (deUint32 i = 0; i < size; ++i)
256                 pBytes[i] = pattern[i % DE_LENGTH_OF_ARRAY(pattern)];
257 }
258
259 //! Get size in bytes of a pixel buffer with given extent.
260 VkDeviceSize getPixelBufferSize (const VkFormat format, const VkExtent3D& extent)
261 {
262         const int pixelSize = tcu::getPixelSize(mapVkFormat(format));
263         return (pixelSize * extent.width * extent.height * extent.depth);
264 }
265
266 //! Determine the size of a 2D image that can hold sizeBytes data.
267 VkExtent3D get2DImageExtentWithSize (const VkDeviceSize sizeBytes, const deUint32 pixelSize)
268 {
269         const deUint32 size = static_cast<deUint32>(sizeBytes / pixelSize);
270
271         DE_ASSERT(size <= MAX_IMAGE_DIMENSION_2D * MAX_IMAGE_DIMENSION_2D);
272
273         return makeExtent3D(
274                 std::min(size, static_cast<deUint32>(MAX_IMAGE_DIMENSION_2D)),
275                 (size / MAX_IMAGE_DIMENSION_2D) + (size % MAX_IMAGE_DIMENSION_2D != 0 ? 1u : 0u),
276                 1u);
277 }
278
279 VkClearValue makeClearValue (const VkFormat format)
280 {
281         if (isDepthStencilFormat(format))
282                 return makeClearValueDepthStencil(0.4f, 21u);
283         else
284         {
285                 if (isIntFormat(format) || isUintFormat(format))
286                         return makeClearValueColorU32(8u, 16u, 24u, 32u);
287                 else
288                         return makeClearValueColorF32(0.25f, 0.49f, 0.75f, 1.0f);
289         }
290 }
291
292 void clearPixelBuffer (tcu::PixelBufferAccess& pixels, const VkClearValue& clearValue)
293 {
294         const tcu::TextureFormat                format                  = pixels.getFormat();
295         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
296
297         if (format.order == tcu::TextureFormat::D)
298         {
299                 for (int z = 0; z < pixels.getDepth(); z++)
300                 for (int y = 0; y < pixels.getHeight(); y++)
301                 for (int x = 0; x < pixels.getWidth(); x++)
302                         pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
303         }
304         else if (format.order == tcu::TextureFormat::S)
305         {
306                 for (int z = 0; z < pixels.getDepth(); z++)
307                 for (int y = 0; y < pixels.getHeight(); y++)
308                 for (int x = 0; x < pixels.getWidth(); x++)
309                         pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
310         }
311         else if (format.order == tcu::TextureFormat::DS)
312         {
313                 for (int z = 0; z < pixels.getDepth(); z++)
314                 for (int y = 0; y < pixels.getHeight(); y++)
315                 for (int x = 0; x < pixels.getWidth(); x++)
316                 {
317                         pixels.setPixDepth(clearValue.depthStencil.depth, x, y, z);
318                         pixels.setPixStencil(clearValue.depthStencil.stencil, x, y, z);
319                 }
320         }
321         else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
322         {
323                 const tcu::UVec4 color (clearValue.color.uint32);
324
325                 for (int z = 0; z < pixels.getDepth(); z++)
326                 for (int y = 0; y < pixels.getHeight(); y++)
327                 for (int x = 0; x < pixels.getWidth(); x++)
328                         pixels.setPixel(color, x, y, z);
329         }
330         else
331         {
332                 const tcu::Vec4 color (clearValue.color.float32);
333
334                 for (int z = 0; z < pixels.getDepth(); z++)
335                 for (int y = 0; y < pixels.getHeight(); y++)
336                 for (int x = 0; x < pixels.getWidth(); x++)
337                         pixels.setPixel(color, x, y, z);
338         }
339 }
340
341 //! Storage image format that requires StorageImageExtendedFormats SPIR-V capability (listed only Vulkan-defined formats).
342 bool isStorageImageExtendedFormat (const VkFormat format)
343 {
344         switch (format)
345         {
346                 case VK_FORMAT_R32G32_SFLOAT:
347                 case VK_FORMAT_R32G32_SINT:
348                 case VK_FORMAT_R32G32_UINT:
349                 case VK_FORMAT_R16G16B16A16_UNORM:
350                 case VK_FORMAT_R16G16B16A16_SNORM:
351                 case VK_FORMAT_R16G16_SFLOAT:
352                 case VK_FORMAT_R16G16_UNORM:
353                 case VK_FORMAT_R16G16_SNORM:
354                 case VK_FORMAT_R16G16_SINT:
355                 case VK_FORMAT_R16G16_UINT:
356                 case VK_FORMAT_R16_SFLOAT:
357                 case VK_FORMAT_R16_UNORM:
358                 case VK_FORMAT_R16_SNORM:
359                 case VK_FORMAT_R16_SINT:
360                 case VK_FORMAT_R16_UINT:
361                 case VK_FORMAT_R8G8_UNORM:
362                 case VK_FORMAT_R8G8_SNORM:
363                 case VK_FORMAT_R8G8_SINT:
364                 case VK_FORMAT_R8G8_UINT:
365                 case VK_FORMAT_R8_UNORM:
366                 case VK_FORMAT_R8_SNORM:
367                 case VK_FORMAT_R8_SINT:
368                 case VK_FORMAT_R8_UINT:
369                         return true;
370
371                 default:
372                         return false;
373         }
374 }
375
376 VkImageViewType getImageViewType (const VkImageType imageType)
377 {
378         switch (imageType)
379         {
380                 case VK_IMAGE_TYPE_1D:          return VK_IMAGE_VIEW_TYPE_1D;
381                 case VK_IMAGE_TYPE_2D:          return VK_IMAGE_VIEW_TYPE_2D;
382                 case VK_IMAGE_TYPE_3D:          return VK_IMAGE_VIEW_TYPE_3D;
383
384                 default:
385                         DE_ASSERT(0);
386                         return VK_IMAGE_VIEW_TYPE_LAST;
387         }
388 }
389
390 std::string getShaderImageType (const VkFormat format, const VkImageType imageType)
391 {
392         const tcu::TextureFormat        texFormat       = mapVkFormat(format);
393         const std::string                       formatPart      = tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
394                                                                                           tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
395         switch (imageType)
396         {
397                 case VK_IMAGE_TYPE_1D:  return formatPart + "image1D";
398                 case VK_IMAGE_TYPE_2D:  return formatPart + "image2D";
399                 case VK_IMAGE_TYPE_3D:  return formatPart + "image3D";
400
401                 default:
402                         DE_ASSERT(false);
403                         return DE_NULL;
404         }
405 }
406
407 std::string getShaderImageFormatQualifier (const VkFormat format)
408 {
409         const tcu::TextureFormat        texFormat       = mapVkFormat(format);
410         const char*                                     orderPart       = DE_NULL;
411         const char*                                     typePart        = DE_NULL;
412
413         switch (texFormat.order)
414         {
415                 case tcu::TextureFormat::R:             orderPart = "r";        break;
416                 case tcu::TextureFormat::RG:    orderPart = "rg";       break;
417                 case tcu::TextureFormat::RGB:   orderPart = "rgb";      break;
418                 case tcu::TextureFormat::RGBA:  orderPart = "rgba";     break;
419
420                 default:
421                         DE_ASSERT(false);
422                         break;
423         }
424
425         switch (texFormat.type)
426         {
427                 case tcu::TextureFormat::FLOAT:                         typePart = "32f";               break;
428                 case tcu::TextureFormat::HALF_FLOAT:            typePart = "16f";               break;
429
430                 case tcu::TextureFormat::UNSIGNED_INT32:        typePart = "32ui";              break;
431                 case tcu::TextureFormat::UNSIGNED_INT16:        typePart = "16ui";              break;
432                 case tcu::TextureFormat::UNSIGNED_INT8:         typePart = "8ui";               break;
433
434                 case tcu::TextureFormat::SIGNED_INT32:          typePart = "32i";               break;
435                 case tcu::TextureFormat::SIGNED_INT16:          typePart = "16i";               break;
436                 case tcu::TextureFormat::SIGNED_INT8:           typePart = "8i";                break;
437
438                 case tcu::TextureFormat::UNORM_INT16:           typePart = "16";                break;
439                 case tcu::TextureFormat::UNORM_INT8:            typePart = "8";                 break;
440
441                 case tcu::TextureFormat::SNORM_INT16:           typePart = "16_snorm";  break;
442                 case tcu::TextureFormat::SNORM_INT8:            typePart = "8_snorm";   break;
443
444                 default:
445                         DE_ASSERT(false);
446                         break;
447         }
448
449         return std::string() + orderPart + typePart;
450 }
451
452 namespace FillUpdateBuffer
453 {
454
455 enum BufferOp
456 {
457         BUFFER_OP_FILL,
458         BUFFER_OP_UPDATE,
459 };
460
461 class Implementation : public Operation
462 {
463 public:
464         Implementation (OperationContext& context, Resource& resource, const BufferOp bufferOp)
465                 : m_context             (context)
466                 , m_resource    (resource)
467                 , m_fillValue   (0x13)
468                 , m_bufferOp    (bufferOp)
469         {
470                 DE_ASSERT((m_resource.getBuffer().size % sizeof(deUint32)) == 0);
471                 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_resource.getBuffer().size <= MAX_UPDATE_BUFFER_SIZE);
472
473                 m_data.resize(static_cast<size_t>(m_resource.getBuffer().size));
474
475                 if (m_bufferOp == BUFFER_OP_FILL)
476                 {
477                         const std::size_t size = m_data.size() / sizeof(m_fillValue);
478                         deUint32* pData = reinterpret_cast<deUint32*>(&m_data[0]);
479                         for (deUint32 i = 0; i < size; ++i)
480                                 pData[i] = m_fillValue;
481                 }
482                 else if (m_bufferOp == BUFFER_OP_UPDATE)
483                         fillPattern(&m_data[0], m_data.size());
484         }
485
486         void recordCommands (const VkCommandBuffer cmdBuffer)
487         {
488                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
489
490                 if (m_bufferOp == BUFFER_OP_FILL)
491                         vk.cmdFillBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_fillValue);
492                 else if (m_bufferOp == BUFFER_OP_UPDATE)
493                         vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, reinterpret_cast<deUint32*>(&m_data[0]));
494         }
495
496         SyncInfo getSyncInfo (void) const
497         {
498                 const SyncInfo syncInfo =
499                 {
500                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
501                         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags                        accessMask;
502                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
503                 };
504                 return syncInfo;
505         }
506
507         Data getData (void) const
508         {
509                 const Data data =
510                 {
511                         m_data.size(),          // std::size_t          size;
512                         &m_data[0],                     // const deUint8*       data;
513                 };
514                 return data;
515         }
516
517 private:
518         OperationContext&               m_context;
519         Resource&                               m_resource;
520         std::vector<deUint8>    m_data;
521         const deUint32                  m_fillValue;
522         const BufferOp                  m_bufferOp;
523 };
524
525 class Support : public OperationSupport
526 {
527 public:
528         Support (const ResourceDescription& resourceDesc, const BufferOp bufferOp)
529                 : m_resourceDesc        (resourceDesc)
530                 , m_bufferOp            (bufferOp)
531         {
532                 DE_ASSERT(m_bufferOp == BUFFER_OP_FILL || m_bufferOp == BUFFER_OP_UPDATE);
533                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
534         }
535
536         deUint32 getResourceUsageFlags (void) const
537         {
538                 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
539         }
540
541         VkQueueFlags getQueueFlags (void) const
542         {
543                 return VK_QUEUE_TRANSFER_BIT;
544         }
545
546         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
547         {
548                 return de::MovePtr<Operation>(new Implementation(context, resource, m_bufferOp));
549         }
550
551 private:
552         const ResourceDescription       m_resourceDesc;
553         const BufferOp                          m_bufferOp;
554 };
555
556 } // FillUpdateBuffer ns
557
558 namespace CopyBuffer
559 {
560
561 class Implementation : public Operation
562 {
563 public:
564         Implementation (OperationContext& context, Resource& resource, const AccessMode mode)
565                 : m_context             (context)
566                 , m_resource    (resource)
567                 , m_mode                (mode)
568         {
569                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
570                 const VkDevice                  device          = m_context.getDevice();
571                 Allocator&                              allocator       = m_context.getAllocator();
572
573                 const VkBufferUsageFlags hostBufferUsage = (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
574
575                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
576                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, hostBufferUsage), MemoryRequirement::HostVisible));
577
578                 const Allocation& alloc = m_hostBuffer->getAllocation();
579                 if (m_mode == ACCESS_MODE_READ)
580                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
581                 else
582                         fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
583                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_resource.getBuffer().size);
584         }
585
586         void recordCommands (const VkCommandBuffer cmdBuffer)
587         {
588                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
589                 const VkBufferCopy              copyRegion      = makeBufferCopy(0u, 0u, m_resource.getBuffer().size);
590
591                 if (m_mode == ACCESS_MODE_READ)
592                 {
593                         vk.cmdCopyBuffer(cmdBuffer, m_resource.getBuffer().handle, **m_hostBuffer, 1u, &copyRegion);
594
595                         // Insert a barrier so copied data is available to the host
596                         const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_resource.getBuffer().size);
597                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
598                 }
599                 else
600                         vk.cmdCopyBuffer(cmdBuffer, **m_hostBuffer, m_resource.getBuffer().handle, 1u, &copyRegion);
601         }
602
603         SyncInfo getSyncInfo (void) const
604         {
605                 const VkAccessFlags access              = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_TRANSFER_WRITE_BIT);
606                 const SyncInfo          syncInfo        =
607                 {
608                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
609                         access,                                                         // VkAccessFlags                        accessMask;
610                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
611                 };
612                 return syncInfo;
613         }
614
615         Data getData (void) const
616         {
617                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
618         }
619
620 private:
621         OperationContext&               m_context;
622         Resource&                               m_resource;
623         const AccessMode                m_mode;
624         de::MovePtr<Buffer>             m_hostBuffer;
625 };
626
627 class Support : public OperationSupport
628 {
629 public:
630         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
631                 : m_mode                        (mode)
632         {
633                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_BUFFER);
634                 DE_UNREF(resourceDesc);
635         }
636
637         deUint32 getResourceUsageFlags (void) const
638         {
639                 return (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
640         }
641
642         VkQueueFlags getQueueFlags (void) const
643         {
644                 return VK_QUEUE_TRANSFER_BIT;
645         }
646
647         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
648         {
649                 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
650         }
651
652 private:
653         const AccessMode                        m_mode;
654 };
655
656 } // CopyBuffer ns
657
658 namespace CopyBlitImage
659 {
660
661 class ImplementationBase : public Operation
662 {
663 public:
664         //! Copy/Blit/Resolve etc. operation
665         virtual void recordCopyCommand (const VkCommandBuffer cmdBuffer) = 0;
666
667         ImplementationBase (OperationContext& context, Resource& resource, const AccessMode mode)
668                 : m_context             (context)
669                 , m_resource    (resource)
670                 , m_mode                (mode)
671                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
672         {
673                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
674                 const VkDevice                  device          = m_context.getDevice();
675                 Allocator&                              allocator       = m_context.getAllocator();
676
677                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
678                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
679                         MemoryRequirement::HostVisible));
680
681                 const Allocation& alloc = m_hostBuffer->getAllocation();
682                 if (m_mode == ACCESS_MODE_READ)
683                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
684                 else
685                         fillPattern(alloc.getHostPtr(), m_bufferSize);
686                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_bufferSize);
687
688                 // Staging image
689                 m_image = de::MovePtr<Image>(new Image(
690                         vk, device, allocator,
691                         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),
692                         MemoryRequirement::Any));
693         }
694
695         void recordCommands (const VkCommandBuffer cmdBuffer)
696         {
697                 const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
698                 const VkBufferImageCopy         bufferCopyRegion        = makeBufferImageCopy(m_resource.getImage().subresourceLayers, m_resource.getImage().extent);
699
700                 const VkImageMemoryBarrier stagingImageTransferSrcLayoutBarrier = makeImageMemoryBarrier(
701                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
702                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
703                         **m_image, m_resource.getImage().subresourceRange);
704
705                 // Staging image layout
706                 {
707                         const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
708                                 (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
709                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
710                                 **m_image, m_resource.getImage().subresourceRange);
711
712                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
713                                 0u, DE_NULL, 0u, DE_NULL, 1u, &layoutBarrier);
714                 }
715
716                 if (m_mode == ACCESS_MODE_READ)
717                 {
718                         // Resource Image -> Staging image
719                         recordCopyCommand(cmdBuffer);
720
721                         // Staging image layout
722                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
723                                 0u, DE_NULL, 0u, DE_NULL, 1u, &stagingImageTransferSrcLayoutBarrier);
724
725                         // Image -> Host buffer
726                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
727
728                         // Insert a barrier so copied data is available to the host
729                         const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_bufferSize);
730                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
731                 }
732                 else
733                 {
734                         // Host buffer -> Staging image
735                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
736
737                         // Staging image layout
738                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
739                                 0u, DE_NULL, 0u, DE_NULL, 1u, &stagingImageTransferSrcLayoutBarrier);
740
741                         // Resource image layout
742                         {
743                                 const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
744                                         (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
745                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
746                                         m_resource.getImage().handle, m_resource.getImage().subresourceRange);
747
748                                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
749                                         0u, DE_NULL, 0u, DE_NULL, 1u, &layoutBarrier);
750                         }
751
752                         // Staging image -> Resource Image
753                         recordCopyCommand(cmdBuffer);
754                 }
755         }
756
757         SyncInfo getSyncInfo (void) const
758         {
759                 const VkAccessFlags access              = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_TRANSFER_WRITE_BIT);
760                 const VkImageLayout layout              = (m_mode == ACCESS_MODE_READ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
761                 const SyncInfo          syncInfo        =
762                 {
763                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
764                         access,                                                         // VkAccessFlags                        accessMask;
765                         layout,                                                         // VkImageLayout                        imageLayout;
766                 };
767                 return syncInfo;
768         }
769
770         Data getData (void) const
771         {
772                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
773         }
774
775 protected:
776         OperationContext&               m_context;
777         Resource&                               m_resource;
778         const AccessMode                m_mode;
779         const VkDeviceSize              m_bufferSize;
780         de::MovePtr<Buffer>             m_hostBuffer;
781         de::MovePtr<Image>              m_image;
782 };
783
784 VkOffset3D makeExtentOffset (const Resource& resource)
785 {
786         DE_ASSERT(resource.getType() == RESOURCE_TYPE_IMAGE);
787         const VkExtent3D extent = resource.getImage().extent;
788
789         switch (resource.getImage().imageType)
790         {
791                 case VK_IMAGE_TYPE_1D:  return makeOffset3D(extent.width, 1, 1);
792                 case VK_IMAGE_TYPE_2D:  return makeOffset3D(extent.width, extent.height, 1);
793                 case VK_IMAGE_TYPE_3D:  return makeOffset3D(extent.width, extent.height, extent.depth);
794                 default:
795                         DE_ASSERT(0);
796                         return VkOffset3D();
797         }
798 }
799
800 VkImageBlit makeBlitRegion (const Resource& resource)
801 {
802         const VkImageBlit blitRegion =
803         {
804                 resource.getImage().subresourceLayers,                                  // VkImageSubresourceLayers    srcSubresource;
805                 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) },  // VkOffset3D                  srcOffsets[2];
806                 resource.getImage().subresourceLayers,                                  // VkImageSubresourceLayers    dstSubresource;
807                 { makeOffset3D(0, 0, 0), makeExtentOffset(resource) },  // VkOffset3D                  dstOffsets[2];
808         };
809         return blitRegion;
810 }
811
812 class BlitImplementation : public ImplementationBase
813 {
814 public:
815         BlitImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
816                 : ImplementationBase    (context, resource, mode)
817                 , m_blitRegion                  (makeBlitRegion(m_resource))
818         {
819                 const InstanceInterface&        vki                             = m_context.getInstanceInterface();
820                 const VkPhysicalDevice          physDevice              = m_context.getPhysicalDevice();
821                 const VkFormatProperties        formatProps             = getPhysicalDeviceFormatProperties(vki, physDevice, m_resource.getImage().format);
822                 const VkFormatFeatureFlags      requiredFlags   = (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
823
824                 // SRC and DST blit is required because both images are using the same format.
825                 if ((formatProps.optimalTilingFeatures & requiredFlags) != requiredFlags)
826                         TCU_THROW(NotSupportedError, "Format doesn't support blits");
827         }
828
829         void recordCopyCommand (const VkCommandBuffer cmdBuffer)
830         {
831                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
832
833                 if (m_mode == ACCESS_MODE_READ)
834                 {
835                         // Resource Image -> Staging image
836                         vk.cmdBlitImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
837                                 1u, &m_blitRegion, VK_FILTER_NEAREST);
838                 }
839                 else
840                 {
841                         // Staging image -> Resource Image
842                         vk.cmdBlitImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
843                                 1u, &m_blitRegion, VK_FILTER_NEAREST);
844                 }
845         }
846
847 private:
848         const VkImageBlit       m_blitRegion;
849 };
850
851 VkImageCopy makeImageCopyRegion (const Resource& resource)
852 {
853         const VkImageCopy imageCopyRegion =
854         {
855                 resource.getImage().subresourceLayers,          // VkImageSubresourceLayers    srcSubresource;
856                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  srcOffset;
857                 resource.getImage().subresourceLayers,          // VkImageSubresourceLayers    dstSubresource;
858                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  dstOffset;
859                 resource.getImage().extent,                                     // VkExtent3D                  extent;
860         };
861         return imageCopyRegion;
862 }
863
864 class CopyImplementation : public ImplementationBase
865 {
866 public:
867         CopyImplementation (OperationContext& context, Resource& resource, const AccessMode mode)
868                 : ImplementationBase    (context, resource, mode)
869                 , m_imageCopyRegion             (makeImageCopyRegion(m_resource))
870         {
871         }
872
873         void recordCopyCommand (const VkCommandBuffer cmdBuffer)
874         {
875                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
876
877                 if (m_mode == ACCESS_MODE_READ)
878                 {
879                         // Resource Image -> Staging image
880                         vk.cmdCopyImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
881                 }
882                 else
883                 {
884                         // Staging image -> Resource Image
885                         vk.cmdCopyImage(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &m_imageCopyRegion);
886                 }
887         }
888
889 private:
890         const VkImageCopy       m_imageCopyRegion;
891 };
892
893 enum Type
894 {
895         TYPE_COPY,
896         TYPE_BLIT,
897 };
898
899 class Support : public OperationSupport
900 {
901 public:
902         Support (const ResourceDescription& resourceDesc, const Type type, const AccessMode mode)
903                 : m_type                                (type)
904                 , m_mode                                (mode)
905         {
906                 DE_ASSERT(resourceDesc.type == RESOURCE_TYPE_IMAGE);
907
908                 const bool isDepthStencil       = isDepthStencilFormat(resourceDesc.imageFormat);
909                 m_requiredQueueFlags            = (isDepthStencil || m_type == TYPE_BLIT ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT);
910
911                 // Don't blit depth/stencil images.
912                 DE_ASSERT(m_type != TYPE_BLIT || !isDepthStencil);
913         }
914
915         deUint32 getResourceUsageFlags (void) const
916         {
917                 return (m_mode == ACCESS_MODE_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT);
918         }
919
920         VkQueueFlags getQueueFlags (void) const
921         {
922                 return m_requiredQueueFlags;
923         }
924
925         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
926         {
927                 if (m_type == TYPE_COPY)
928                         return de::MovePtr<Operation>(new CopyImplementation(context, resource, m_mode));
929                 else
930                         return de::MovePtr<Operation>(new BlitImplementation(context, resource, m_mode));
931         }
932
933 private:
934         const Type                      m_type;
935         const AccessMode        m_mode;
936         VkQueueFlags            m_requiredQueueFlags;
937 };
938
939 } // CopyBlitImage ns
940
941 namespace ShaderAccess
942 {
943
944 enum DispatchCall
945 {
946         DISPATCH_CALL_DISPATCH,
947         DISPATCH_CALL_DISPATCH_INDIRECT,
948 };
949
950 class GraphicsPipeline : public Pipeline
951 {
952 public:
953         GraphicsPipeline (OperationContext& context, const VkShaderStageFlagBits stage, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
954                 : m_vertices    (context)
955         {
956                 const DeviceInterface&          vk                              = context.getDeviceInterface();
957                 const VkDevice                          device                  = context.getDevice();
958                 Allocator&                                      allocator               = context.getAllocator();
959                 const VkShaderStageFlags        requiredStages  = getRequiredStages(stage);
960
961                 // Color attachment
962
963                 m_colorFormat                                   = VK_FORMAT_R8G8B8A8_UNORM;
964                 m_colorImageSubresourceRange    = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
965                 m_colorImageExtent                              = makeExtent3D(16u, 16u, 1u);
966                 m_colorAttachmentImage                  = de::MovePtr<Image>(new Image(vk, device, allocator,
967                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
968                         MemoryRequirement::Any));
969
970                 // Pipeline
971
972                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
973                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
974                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height, 1u);
975                 m_pipelineLayout                = makePipelineLayout(vk, device, descriptorSetLayout);
976
977                 GraphicsPipelineBuilder pipelineBuilder;
978                 pipelineBuilder
979                         .setRenderSize                                  (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
980                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
981                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
982                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
983
984                 if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
985                         pipelineBuilder
986                                 .setPatchControlPoints  (m_vertices.getNumVertices())
987                                 .setShader                              (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,          context.getBinaryCollection().get(shaderPrefix + "tesc"), DE_NULL)
988                                 .setShader                              (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,       context.getBinaryCollection().get(shaderPrefix + "tese"), DE_NULL);
989
990                 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
991                         pipelineBuilder
992                                 .setShader      (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,      context.getBinaryCollection().get(shaderPrefix + "geom"), DE_NULL);
993
994                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
995         }
996
997         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
998         {
999                 const DeviceInterface&  vk      = context.getDeviceInterface();
1000
1001                 // Change color attachment image layout
1002                 {
1003                         const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
1004                                 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1005                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1006                                 **m_colorAttachmentImage, m_colorImageSubresourceRange);
1007
1008                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1009                                 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
1010                 }
1011
1012                 {
1013                         const VkRect2D renderArea = {
1014                                 makeOffset2D(0, 0),
1015                                 makeExtent2D(m_colorImageExtent.width, m_colorImageExtent.height),
1016                         };
1017                         const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1018
1019                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
1020                 }
1021
1022                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1023                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1024                 {
1025                         const VkDeviceSize      vertexBufferOffset      = 0ull;
1026                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
1027                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1028                 }
1029
1030                 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
1031                 endRenderPass(vk, cmdBuffer);
1032         }
1033
1034 private:
1035         const VertexGrid                        m_vertices;
1036         VkFormat                                        m_colorFormat;
1037         de::MovePtr<Image>                      m_colorAttachmentImage;
1038         Move<VkImageView>                       m_colorAttachmentView;
1039         VkExtent3D                                      m_colorImageExtent;
1040         VkImageSubresourceRange         m_colorImageSubresourceRange;
1041         Move<VkRenderPass>                      m_renderPass;
1042         Move<VkFramebuffer>                     m_framebuffer;
1043         Move<VkPipelineLayout>          m_pipelineLayout;
1044         Move<VkPipeline>                        m_pipeline;
1045 };
1046
1047 class ComputePipeline : public Pipeline
1048 {
1049 public:
1050         ComputePipeline (OperationContext& context, const DispatchCall dispatchCall, const std::string& shaderPrefix, const VkDescriptorSetLayout descriptorSetLayout)
1051                 : m_dispatchCall        (dispatchCall)
1052         {
1053                 const DeviceInterface&  vk                      = context.getDeviceInterface();
1054                 const VkDevice                  device          = context.getDevice();
1055                 Allocator&                              allocator       = context.getAllocator();
1056
1057                 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1058                 {
1059                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
1060                                 makeBufferCreateInfo(sizeof(VkDispatchIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
1061
1062                         const Allocation&                                       alloc                           = m_indirectBuffer->getAllocation();
1063                         VkDispatchIndirectCommand* const        pIndirectCommand        = static_cast<VkDispatchIndirectCommand*>(alloc.getHostPtr());
1064
1065                         pIndirectCommand->x     = 1u;
1066                         pIndirectCommand->y = 1u;
1067                         pIndirectCommand->z     = 1u;
1068
1069                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeof(VkDispatchIndirectCommand));
1070                 }
1071
1072                 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
1073
1074                 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
1075                 m_pipeline               = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData());
1076         }
1077
1078         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
1079         {
1080                 const DeviceInterface&  vk      = context.getDeviceInterface();
1081
1082                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
1083                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1084
1085                 if (m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT)
1086                         vk.cmdDispatchIndirect(cmdBuffer, **m_indirectBuffer, 0u);
1087                 else
1088                         vk.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1089         }
1090
1091 private:
1092         const DispatchCall                      m_dispatchCall;
1093         de::MovePtr<Buffer>                     m_indirectBuffer;
1094         Move<VkPipelineLayout>          m_pipelineLayout;
1095         Move<VkPipeline>                        m_pipeline;
1096 };
1097
1098 //! Read/write operation on a UBO/SSBO in graphics/compute pipeline.
1099 class BufferImplementation : public Operation
1100 {
1101 public:
1102         BufferImplementation (OperationContext&                         context,
1103                                                   Resource&                                             resource,
1104                                                   const VkShaderStageFlagBits   stage,
1105                                                   const BufferType                              bufferType,
1106                                                   const std::string&                    shaderPrefix,
1107                                                   const AccessMode                              mode,
1108                                                   const PipelineType                    pipelineType,
1109                                                   const DispatchCall                    dispatchCall)
1110                 : m_context                     (context)
1111                 , m_resource            (resource)
1112                 , m_stage                       (stage)
1113                 , m_pipelineStage       (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1114                 , m_bufferType          (bufferType)
1115                 , m_mode                        (mode)
1116                 , m_dispatchCall        (dispatchCall)
1117         {
1118                 requireFeaturesForSSBOAccess (m_context, m_stage);
1119
1120                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1121                 const VkDevice                  device          = m_context.getDevice();
1122                 Allocator&                              allocator       = m_context.getAllocator();
1123
1124                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1125                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
1126
1127                 // Init host buffer data
1128                 {
1129                         const Allocation& alloc = m_hostBuffer->getAllocation();
1130                         if (m_mode == ACCESS_MODE_READ)
1131                                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_resource.getBuffer().size));
1132                         else
1133                                 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
1134                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_resource.getBuffer().size);
1135                 }
1136
1137                 // Prepare descriptors
1138                 {
1139                         const VkDescriptorType  bufferDescriptorType    = (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1140
1141                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1142                                 .addSingleBinding(bufferDescriptorType, m_stage)
1143                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
1144                                 .build(vk, device);
1145
1146                         m_descriptorPool = DescriptorPoolBuilder()
1147                                 .addType(bufferDescriptorType)
1148                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1149                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1150
1151                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1152
1153                         const VkDescriptorBufferInfo  bufferInfo         = makeDescriptorBufferInfo(m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size);
1154                         const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_resource.getBuffer().size);
1155
1156                         if (m_mode == ACCESS_MODE_READ)
1157                         {
1158                                 DescriptorSetUpdateBuilder()
1159                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), bufferDescriptorType, &bufferInfo)
1160                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1161                                         .update(vk, device);
1162                         }
1163                         else
1164                         {
1165                                 DescriptorSetUpdateBuilder()
1166                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
1167                                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
1168                                         .update(vk, device);
1169                         }
1170                 }
1171
1172                 // Create pipeline
1173                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1174                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1175         }
1176
1177         void recordCommands (const VkCommandBuffer cmdBuffer)
1178         {
1179                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1180
1181                 // Post draw/dispatch commands
1182
1183                 if (m_mode == ACCESS_MODE_READ)
1184                 {
1185                         const DeviceInterface&  vk      = m_context.getDeviceInterface();
1186
1187                         // Insert a barrier so data written by the shader is available to the host
1188                         const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_resource.getBuffer().size);
1189                         vk.cmdPipelineBarrier(cmdBuffer, m_pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
1190                 }
1191         }
1192
1193         SyncInfo getSyncInfo (void) const
1194         {
1195                 const VkAccessFlags     accessFlags = (m_mode == ACCESS_MODE_READ ? (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_ACCESS_UNIFORM_READ_BIT
1196                                                                                                                                                                                                                          : VK_ACCESS_SHADER_READ_BIT)
1197                                                                                                                                           : VK_ACCESS_SHADER_WRITE_BIT);
1198                 const SyncInfo          syncInfo        =
1199                 {
1200                         m_pipelineStage,                                // VkPipelineStageFlags         stageMask;
1201                         accessFlags,                                    // VkAccessFlags                        accessMask;
1202                         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout                        imageLayout;
1203                 };
1204                 return syncInfo;
1205         }
1206
1207         Data getData (void) const
1208         {
1209                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
1210         }
1211
1212 private:
1213         OperationContext&                       m_context;
1214         Resource&                                       m_resource;
1215         const VkShaderStageFlagBits     m_stage;
1216         const VkPipelineStageFlags      m_pipelineStage;
1217         const BufferType                        m_bufferType;
1218         const AccessMode                        m_mode;
1219         const DispatchCall                      m_dispatchCall;
1220         de::MovePtr<Buffer>                     m_hostBuffer;
1221         Move<VkDescriptorPool>          m_descriptorPool;
1222         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
1223         Move<VkDescriptorSet>           m_descriptorSet;
1224         de::MovePtr<Pipeline>           m_pipeline;
1225 };
1226
1227 class ImageImplementation : public Operation
1228 {
1229 public:
1230         ImageImplementation (OperationContext&                          context,
1231                                                  Resource&                                              resource,
1232                                                  const VkShaderStageFlagBits    stage,
1233                                                  const std::string&                             shaderPrefix,
1234                                                  const AccessMode                               mode,
1235                                                  const PipelineType                             pipelineType,
1236                                                  const DispatchCall                             dispatchCall)
1237                 : m_context                             (context)
1238                 , m_resource                    (resource)
1239                 , m_stage                               (stage)
1240                 , m_pipelineStage               (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
1241                 , m_mode                                (mode)
1242                 , m_dispatchCall                (dispatchCall)
1243                 , m_hostBufferSizeBytes (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
1244         {
1245                 const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1246                 const InstanceInterface&        vki                     = m_context.getInstanceInterface();
1247                 const VkDevice                          device          = m_context.getDevice();
1248                 const VkPhysicalDevice          physDevice      = m_context.getPhysicalDevice();
1249                 Allocator&                                      allocator       = m_context.getAllocator();
1250
1251                 // Image stores are always required, in either access mode.
1252                 requireFeaturesForSSBOAccess(m_context, m_stage);
1253
1254                 // Some storage image formats require additional capability.
1255                 if (isStorageImageExtendedFormat(m_resource.getImage().format))
1256                         requireFeatures(vki, physDevice, FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS);
1257
1258                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1259                         vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1260                         MemoryRequirement::HostVisible));
1261
1262                 // Init host buffer data
1263                 {
1264                         const Allocation& alloc = m_hostBuffer->getAllocation();
1265                         if (m_mode == ACCESS_MODE_READ)
1266                                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
1267                         else
1268                                 fillPattern(alloc.getHostPtr(), m_hostBufferSizeBytes);
1269                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_hostBufferSizeBytes);
1270                 }
1271
1272                 // Image resources
1273                 {
1274                         m_image = de::MovePtr<Image>(new Image(vk, device, allocator,
1275                                 makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format,
1276                                                                         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
1277                                 MemoryRequirement::Any));
1278
1279                         if (m_mode == ACCESS_MODE_READ)
1280                         {
1281                                 m_srcImage = &m_resource.getImage().handle;
1282                                 m_dstImage = &(**m_image);
1283                         }
1284                         else
1285                         {
1286                                 m_srcImage = &(**m_image);
1287                                 m_dstImage = &m_resource.getImage().handle;
1288                         }
1289
1290                         const VkImageViewType viewType = getImageViewType(m_resource.getImage().imageType);
1291
1292                         m_srcImageView  = makeImageView(vk, device, *m_srcImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1293                         m_dstImageView  = makeImageView(vk, device, *m_dstImage, viewType, m_resource.getImage().format, m_resource.getImage().subresourceRange);
1294                 }
1295
1296                 // Prepare descriptors
1297                 {
1298                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1299                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1300                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_stage)
1301                                 .build(vk, device);
1302
1303                         m_descriptorPool = DescriptorPoolBuilder()
1304                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1305                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1306                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1307
1308                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1309
1310                         const VkDescriptorImageInfo srcImageInfo = makeDescriptorImageInfo(DE_NULL, *m_srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1311                         const VkDescriptorImageInfo dstImageInfo = makeDescriptorImageInfo(DE_NULL, *m_dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1312
1313                         DescriptorSetUpdateBuilder()
1314                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &srcImageInfo)
1315                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &dstImageInfo)
1316                                 .update(vk, device);
1317                 }
1318
1319                 // Create pipeline
1320                 m_pipeline = (pipelineType == PIPELINE_TYPE_GRAPHICS ? de::MovePtr<Pipeline>(new GraphicsPipeline(context, stage, shaderPrefix, *m_descriptorSetLayout))
1321                                                                                                                          : de::MovePtr<Pipeline>(new ComputePipeline(context, m_dispatchCall, shaderPrefix, *m_descriptorSetLayout)));
1322         }
1323
1324         void recordCommands (const VkCommandBuffer cmdBuffer)
1325         {
1326                 const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
1327                 const VkBufferImageCopy bufferCopyRegion        = makeBufferImageCopy(m_resource.getImage().subresourceLayers, m_resource.getImage().extent);
1328
1329                 // Destination image layout
1330                 {
1331                         const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
1332                                 (VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT,
1333                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1334                                 *m_dstImage, m_resource.getImage().subresourceRange);
1335
1336                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, m_pipelineStage, (VkDependencyFlags)0,
1337                                 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1338                 }
1339
1340                 // In write mode, source image must be filled with data.
1341                 if (m_mode == ACCESS_MODE_WRITE)
1342                 {
1343                         // Layout for transfer
1344                         {
1345                                 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
1346                                         (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
1347                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1348                                         *m_srcImage, m_resource.getImage().subresourceRange);
1349
1350                                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
1351                                         0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1352                         }
1353
1354                         // Host buffer -> Src image
1355                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, *m_srcImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferCopyRegion);
1356
1357                         // Layout for shader reading
1358                         {
1359                                 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
1360                                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1361                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1362                                         *m_srcImage, m_resource.getImage().subresourceRange);
1363
1364                                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, m_pipelineStage, (VkDependencyFlags)0,
1365                                         0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1366                         }
1367                 }
1368
1369                 // Execute shaders
1370
1371                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
1372
1373                 // Post draw/dispatch commands
1374
1375                 if (m_mode == ACCESS_MODE_READ)
1376                 {
1377                         // Layout for transfer
1378                         {
1379                                 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
1380                                         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1381                                         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1382                                         *m_dstImage, m_resource.getImage().subresourceRange);
1383
1384                                 vk.cmdPipelineBarrier(cmdBuffer, m_pipelineStage, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
1385                                         0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1386                         }
1387
1388                         // Dst image -> Host buffer
1389                         vk.cmdCopyImageToBuffer(cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &bufferCopyRegion);
1390
1391                         // Insert a barrier so data written by the shader is available to the host
1392                         {
1393                                 const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_hostBufferSizeBytes);
1394                                 vk.cmdPipelineBarrier(cmdBuffer, m_pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
1395                         }
1396                 }
1397         }
1398
1399         SyncInfo getSyncInfo (void) const
1400         {
1401                 const VkAccessFlags     accessFlags = (m_mode == ACCESS_MODE_READ ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_SHADER_WRITE_BIT);
1402                 const SyncInfo          syncInfo        =
1403                 {
1404                         m_pipelineStage,                        // VkPipelineStageFlags         stageMask;
1405                         accessFlags,                            // VkAccessFlags                        accessMask;
1406                         VK_IMAGE_LAYOUT_GENERAL,        // VkImageLayout                        imageLayout;
1407                 };
1408                 return syncInfo;
1409         }
1410
1411         Data getData (void) const
1412         {
1413                 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
1414         }
1415
1416 private:
1417         OperationContext&                       m_context;
1418         Resource&                                       m_resource;
1419         const VkShaderStageFlagBits     m_stage;
1420         const VkPipelineStageFlags      m_pipelineStage;
1421         const AccessMode                        m_mode;
1422         const DispatchCall                      m_dispatchCall;
1423         const VkDeviceSize                      m_hostBufferSizeBytes;
1424         de::MovePtr<Buffer>                     m_hostBuffer;
1425         de::MovePtr<Image>                      m_image;                        //! Additional image used as src or dst depending on operation mode.
1426         const VkImage*                          m_srcImage;
1427         const VkImage*                          m_dstImage;
1428         Move<VkImageView>                       m_srcImageView;
1429         Move<VkImageView>                       m_dstImageView;
1430         Move<VkDescriptorPool>          m_descriptorPool;
1431         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
1432         Move<VkDescriptorSet>           m_descriptorSet;
1433         de::MovePtr<Pipeline>           m_pipeline;
1434 };
1435
1436 //! Create generic passthrough shaders with bits of custom code inserted in a specific shader stage.
1437 void initPassthroughPrograms (SourceCollections&                        programCollection,
1438                                                           const std::string&                    shaderPrefix,
1439                                                           const std::string&                    declCode,
1440                                                           const std::string&                    mainCode,
1441                                                           const VkShaderStageFlagBits   stage)
1442 {
1443         const VkShaderStageFlags        requiredStages  = getRequiredStages(stage);
1444
1445         if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
1446         {
1447                 std::ostringstream src;
1448                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1449                         << "\n"
1450                         << "layout(location = 0) in vec4 v_in_position;\n"
1451                         << "\n"
1452                         << "out " << s_perVertexBlock << ";\n"
1453                         << "\n"
1454                         << (stage & VK_SHADER_STAGE_VERTEX_BIT ? declCode + "\n" : "")
1455                         << "void main (void)\n"
1456                         << "{\n"
1457                         << "    gl_Position = v_in_position;\n"
1458                         << (stage & VK_SHADER_STAGE_VERTEX_BIT ? mainCode : "")
1459                         << "}\n";
1460
1461                 programCollection.glslSources.add(shaderPrefix + "vert") << glu::VertexSource(src.str());
1462         }
1463
1464         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1465         {
1466                 std::ostringstream src;
1467                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1468                         << "\n"
1469                         << "layout(vertices = 3) out;\n"
1470                         << "\n"
1471                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
1472                         << "\n"
1473                         << "out " << s_perVertexBlock << " gl_out[];\n"
1474                         << "\n"
1475                         << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? declCode + "\n" : "")
1476                         << "void main (void)\n"
1477                         << "{\n"
1478                         << "    gl_TessLevelInner[0] = 1.0;\n"
1479                         << "    gl_TessLevelInner[1] = 1.0;\n"
1480                         << "\n"
1481                         << "    gl_TessLevelOuter[0] = 1.0;\n"
1482                         << "    gl_TessLevelOuter[1] = 1.0;\n"
1483                         << "    gl_TessLevelOuter[2] = 1.0;\n"
1484                         << "    gl_TessLevelOuter[3] = 1.0;\n"
1485                         << "\n"
1486                         << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1487                         << (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? "\n" + mainCode : "")
1488                         << "}\n";
1489
1490                 programCollection.glslSources.add(shaderPrefix + "tesc") << glu::TessellationControlSource(src.str());
1491         }
1492
1493         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1494         {
1495                 std::ostringstream src;
1496                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1497                         << "\n"
1498                         << "layout(triangles, equal_spacing, ccw) in;\n"
1499                         << "\n"
1500                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
1501                         << "\n"
1502                         << "out " << s_perVertexBlock << ";\n"
1503                         << "\n"
1504                         << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? declCode + "\n" : "")
1505                         << "void main (void)\n"
1506                         << "{\n"
1507                         << "    vec3 px = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
1508                         << "    vec3 py = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
1509                         << "    vec3 pz = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
1510                         << "    gl_Position = vec4(px + py + pz, 1.0);\n"
1511                         << (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? mainCode : "")
1512                         << "}\n";
1513
1514                 programCollection.glslSources.add(shaderPrefix + "tese") << glu::TessellationEvaluationSource(src.str());
1515         }
1516
1517         if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
1518         {
1519                 std::ostringstream src;
1520                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1521                         << "\n"
1522                         << "layout(triangles) in;\n"
1523                         << "layout(triangle_strip, max_vertices = 3) out;\n"
1524                         << "\n"
1525                         << "in " << s_perVertexBlock << " gl_in[];\n"
1526                         << "\n"
1527                         << "out " << s_perVertexBlock << ";\n"
1528                         << "\n"
1529                         << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? declCode + "\n" : "")
1530                         << "void main (void)\n"
1531                         << "{\n"
1532                         << "    gl_Position = gl_in[0].gl_Position;\n"
1533                         << "    EmitVertex();\n"
1534                         << "\n"
1535                         << "    gl_Position = gl_in[1].gl_Position;\n"
1536                         << "    EmitVertex();\n"
1537                         << "\n"
1538                         << "    gl_Position = gl_in[2].gl_Position;\n"
1539                         << "    EmitVertex();\n"
1540                         << (stage & VK_SHADER_STAGE_GEOMETRY_BIT ? "\n" + mainCode : "")
1541                         << "}\n";
1542
1543                 programCollection.glslSources.add(shaderPrefix + "geom") << glu::GeometrySource(src.str());
1544         }
1545
1546         if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
1547         {
1548                 std::ostringstream src;
1549                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1550                         << "\n"
1551                         << "layout(location = 0) out vec4 o_color;\n"
1552                         << "\n"
1553                         << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? declCode + "\n" : "")
1554                         << "void main (void)\n"
1555                         << "{\n"
1556                         << "    o_color = vec4(1.0);\n"
1557                         << (stage & VK_SHADER_STAGE_FRAGMENT_BIT ? "\n" + mainCode : "")
1558                         << "}\n";
1559
1560                 programCollection.glslSources.add(shaderPrefix + "frag") << glu::FragmentSource(src.str());
1561         }
1562
1563         if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
1564         {
1565                 std::ostringstream src;
1566                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1567                         << "\n"
1568                         << "layout(local_size_x = 1) in;\n"
1569                         << "\n"
1570                         << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? declCode + "\n" : "")
1571                         << "void main (void)\n"
1572                         << "{\n"
1573                         << (stage & VK_SHADER_STAGE_COMPUTE_BIT ? mainCode : "")
1574                         << "}\n";
1575
1576                 programCollection.glslSources.add(shaderPrefix + "comp") << glu::ComputeSource(src.str());
1577         }
1578 }
1579
1580 class BufferSupport : public OperationSupport
1581 {
1582 public:
1583         BufferSupport (const ResourceDescription&       resourceDesc,
1584                                    const BufferType                             bufferType,
1585                                    const AccessMode                             mode,
1586                                    const VkShaderStageFlagBits  stage,
1587                                    const DispatchCall                   dispatchCall = DISPATCH_CALL_DISPATCH)
1588                 : m_resourceDesc        (resourceDesc)
1589                 , m_bufferType          (bufferType)
1590                 , m_mode                        (mode)
1591                 , m_stage                       (stage)
1592                 , m_shaderPrefix        (std::string(m_mode == ACCESS_MODE_READ ? "read_" : "write_") + (m_bufferType == BUFFER_TYPE_UNIFORM ? "ubo_" : "ssbo_"))
1593                 , m_dispatchCall        (dispatchCall)
1594         {
1595                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
1596                 DE_ASSERT(m_bufferType == BUFFER_TYPE_UNIFORM || m_bufferType == BUFFER_TYPE_STORAGE);
1597                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
1598                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_bufferType == BUFFER_TYPE_STORAGE);
1599                 DE_ASSERT(m_bufferType != BUFFER_TYPE_UNIFORM || m_resourceDesc.size.x() <= MAX_UBO_RANGE);
1600                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
1601
1602                 assertValidShaderStage(m_stage);
1603         }
1604
1605         void initPrograms (SourceCollections& programCollection) const
1606         {
1607                 DE_ASSERT((m_resourceDesc.size.x() % sizeof(tcu::UVec4)) == 0);
1608
1609                 const std::string       bufferTypeStr   = (m_bufferType == BUFFER_TYPE_UNIFORM ? "uniform" : "buffer");
1610                 const int                       numVecElements  = static_cast<int>(m_resourceDesc.size.x() / sizeof(tcu::UVec4));  // std140 must be aligned to a multiple of 16
1611
1612                 std::ostringstream declSrc;
1613                 declSrc << "layout(set = 0, binding = 0, std140) readonly " << bufferTypeStr << " Input {\n"
1614                                 << "    uvec4 data[" << numVecElements << "];\n"
1615                                 << "} b_in;\n"
1616                                 << "\n"
1617                                 << "layout(set = 0, binding = 1, std140) writeonly buffer Output {\n"
1618                                 << "    uvec4 data[" << numVecElements << "];\n"
1619                                 << "} b_out;\n";
1620
1621                 std::ostringstream copySrc;
1622                 copySrc << "    for (int i = 0; i < " << numVecElements << "; ++i) {\n"
1623                                 << "        b_out.data[i] = b_in.data[i];\n"
1624                                 << "    }\n";
1625
1626                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), copySrc.str(), m_stage);
1627         }
1628
1629         deUint32 getResourceUsageFlags (void) const
1630         {
1631                 return (m_bufferType == BUFFER_TYPE_UNIFORM ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1632         }
1633
1634         VkQueueFlags getQueueFlags (void) const
1635         {
1636                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
1637         }
1638
1639         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1640         {
1641                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
1642                         return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
1643                 else
1644                         return de::MovePtr<Operation>(new BufferImplementation(context, resource, m_stage, m_bufferType, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
1645         }
1646
1647 private:
1648         const ResourceDescription       m_resourceDesc;
1649         const BufferType                        m_bufferType;
1650         const AccessMode                        m_mode;
1651         const VkShaderStageFlagBits     m_stage;
1652         const std::string                       m_shaderPrefix;
1653         const DispatchCall                      m_dispatchCall;
1654 };
1655
1656 class ImageSupport : public OperationSupport
1657 {
1658 public:
1659         ImageSupport (const ResourceDescription&        resourceDesc,
1660                                   const AccessMode                              mode,
1661                                   const VkShaderStageFlagBits   stage,
1662                                   const DispatchCall                    dispatchCall = DISPATCH_CALL_DISPATCH)
1663                 : m_resourceDesc        (resourceDesc)
1664                 , m_mode                        (mode)
1665                 , m_stage                       (stage)
1666                 , m_shaderPrefix        (m_mode == ACCESS_MODE_READ ? "read_image_" : "write_image_")
1667                 , m_dispatchCall        (dispatchCall)
1668         {
1669                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
1670                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
1671                 DE_ASSERT(m_dispatchCall == DISPATCH_CALL_DISPATCH || m_dispatchCall == DISPATCH_CALL_DISPATCH_INDIRECT);
1672
1673                 assertValidShaderStage(m_stage);
1674         }
1675
1676         void initPrograms (SourceCollections& programCollection) const
1677         {
1678                 const std::string       imageFormat     = getShaderImageFormatQualifier(m_resourceDesc.imageFormat);
1679                 const std::string       imageType       = getShaderImageType(m_resourceDesc.imageFormat, m_resourceDesc.imageType);
1680
1681                 std::ostringstream declSrc;
1682                 declSrc << "layout(set = 0, binding = 0, " << imageFormat << ") readonly  uniform " << imageType << " srcImg;\n"
1683                                 << "layout(set = 0, binding = 1, " << imageFormat << ") writeonly uniform " << imageType << " dstImg;\n";
1684
1685                 std::ostringstream mainSrc;
1686                 if (m_resourceDesc.imageType == VK_IMAGE_TYPE_1D)
1687                         mainSrc << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
1688                                         << "        imageStore(dstImg, x, imageLoad(srcImg, x));\n";
1689                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_2D)
1690                         mainSrc << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
1691                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
1692                                         << "        imageStore(dstImg, ivec2(x, y), imageLoad(srcImg, ivec2(x, y)));\n";
1693                 else if (m_resourceDesc.imageType == VK_IMAGE_TYPE_3D)
1694                         mainSrc << "    for (int z = 0; z < " << m_resourceDesc.size.z() << "; ++z)\n"
1695                                         << "    for (int y = 0; y < " << m_resourceDesc.size.y() << "; ++y)\n"
1696                                         << "    for (int x = 0; x < " << m_resourceDesc.size.x() << "; ++x)\n"
1697                                         << "        imageStore(dstImg, ivec3(x, y, z), imageLoad(srcImg, ivec3(x, y, z)));\n";
1698                 else
1699                         DE_ASSERT(0);
1700
1701                 initPassthroughPrograms(programCollection, m_shaderPrefix, declSrc.str(), mainSrc.str(), m_stage);
1702         }
1703
1704         deUint32 getResourceUsageFlags (void) const
1705         {
1706                 return VK_IMAGE_USAGE_STORAGE_BIT;
1707         }
1708
1709         VkQueueFlags getQueueFlags (void) const
1710         {
1711                 return (m_stage == VK_SHADER_STAGE_COMPUTE_BIT ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
1712         }
1713
1714         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1715         {
1716                 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
1717                         return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_COMPUTE, m_dispatchCall));
1718                 else
1719                         return de::MovePtr<Operation>(new ImageImplementation(context, resource, m_stage, m_shaderPrefix, m_mode, PIPELINE_TYPE_GRAPHICS, m_dispatchCall));
1720         }
1721
1722 private:
1723         const ResourceDescription       m_resourceDesc;
1724         const AccessMode                        m_mode;
1725         const VkShaderStageFlagBits     m_stage;
1726         const std::string                       m_shaderPrefix;
1727         const DispatchCall                      m_dispatchCall;
1728 };
1729
1730 } // ShaderAccess ns
1731
1732 namespace CopyBufferToImage
1733 {
1734
1735 class WriteImplementation : public Operation
1736 {
1737 public:
1738         WriteImplementation (OperationContext& context, Resource& resource)
1739                 : m_context             (context)
1740                 , m_resource    (resource)
1741                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
1742         {
1743                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
1744
1745                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1746                 const VkDevice                  device          = m_context.getDevice();
1747                 Allocator&                              allocator       = m_context.getAllocator();
1748
1749                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1750                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
1751
1752                 const Allocation& alloc = m_hostBuffer->getAllocation();
1753                 fillPattern(alloc.getHostPtr(), m_bufferSize);
1754                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_bufferSize);
1755         }
1756
1757         void recordCommands (const VkCommandBuffer cmdBuffer)
1758         {
1759                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1760                 const VkBufferImageCopy copyRegion      = makeBufferImageCopy(m_resource.getImage().subresourceLayers, m_resource.getImage().extent);
1761
1762                 const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
1763                         (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
1764                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1765                         m_resource.getImage().handle, m_resource.getImage().subresourceRange);
1766                 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);
1767
1768                 vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1769         }
1770
1771         SyncInfo getSyncInfo (void) const
1772         {
1773                 const SyncInfo syncInfo =
1774                 {
1775                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
1776                         VK_ACCESS_TRANSFER_WRITE_BIT,                   // VkAccessFlags                        accessMask;
1777                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
1778                 };
1779                 return syncInfo;
1780         }
1781
1782         Data getData (void) const
1783         {
1784                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
1785         }
1786
1787 private:
1788         OperationContext&               m_context;
1789         Resource&                               m_resource;
1790         de::MovePtr<Buffer>             m_hostBuffer;
1791         const VkDeviceSize              m_bufferSize;
1792 };
1793
1794 class ReadImplementation : public Operation
1795 {
1796 public:
1797         ReadImplementation (OperationContext& context, Resource& resource)
1798                 : m_context                             (context)
1799                 , m_resource                    (resource)
1800                 , m_subresourceRange    (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
1801                 , m_subresourceLayers   (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
1802         {
1803                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
1804
1805                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1806                 const VkDevice                  device          = m_context.getDevice();
1807                 Allocator&                              allocator       = m_context.getAllocator();
1808                 const VkFormat                  format          = VK_FORMAT_R8G8B8A8_UNORM;
1809                 const deUint32                  pixelSize       = tcu::getPixelSize(mapVkFormat(format));
1810
1811                 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
1812                 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);  // there may be some unused space at the end
1813
1814                 // Copy destination image.
1815                 m_image = de::MovePtr<Image>(new Image(
1816                         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));
1817
1818                 // Image data will be copied here, so it can be read on the host.
1819                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1820                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
1821         }
1822
1823         void recordCommands (const VkCommandBuffer cmdBuffer)
1824         {
1825                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1826                 const VkBufferImageCopy copyRegion      = makeBufferImageCopy(m_subresourceLayers, m_imageExtent);
1827
1828                 // Resource -> Image
1829                 {
1830                         const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
1831                                 (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
1832                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1833                                 **m_image, m_subresourceRange);
1834                         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);
1835
1836                         vk.cmdCopyBufferToImage(cmdBuffer, m_resource.getBuffer().handle, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1837                 }
1838                 // Image -> Host buffer
1839                 {
1840                         const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
1841                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1842                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1843                                 **m_image, m_subresourceRange);
1844                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &layoutBarrier);
1845
1846                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
1847
1848                         const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_resource.getBuffer().size);
1849                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
1850                 }
1851         }
1852
1853         SyncInfo getSyncInfo (void) const
1854         {
1855                 const SyncInfo syncInfo =
1856                 {
1857                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
1858                         VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags                        accessMask;
1859                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
1860                 };
1861                 return syncInfo;
1862         }
1863
1864         Data getData (void) const
1865         {
1866                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
1867         }
1868
1869 private:
1870         OperationContext&                               m_context;
1871         Resource&                                               m_resource;
1872         const VkImageSubresourceRange   m_subresourceRange;
1873         const VkImageSubresourceLayers  m_subresourceLayers;
1874         de::MovePtr<Buffer>                             m_hostBuffer;
1875         de::MovePtr<Image>                              m_image;
1876         VkExtent3D                                              m_imageExtent;
1877 };
1878
1879 class Support : public OperationSupport
1880 {
1881 public:
1882         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
1883                 : m_mode                                (mode)
1884                 , m_requiredQueueFlags  (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
1885         {
1886                 // From spec:
1887                 //   Because depth or stencil aspect buffer to image copies may require format conversions on some implementations,
1888                 //   they are not supported on queues that do not support graphics.
1889
1890                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
1891                 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_BUFFER);
1892                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_IMAGE);
1893         }
1894
1895         deUint32 getResourceUsageFlags (void) const
1896         {
1897                 if (m_mode == ACCESS_MODE_READ)
1898                         return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1899                 else
1900                         return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1901         }
1902
1903         VkQueueFlags getQueueFlags (void) const
1904         {
1905                 return m_requiredQueueFlags;
1906         }
1907
1908         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
1909         {
1910                 if (m_mode == ACCESS_MODE_READ)
1911                         return de::MovePtr<Operation>(new ReadImplementation(context, resource));
1912                 else
1913                         return de::MovePtr<Operation>(new WriteImplementation(context, resource));
1914         }
1915
1916 private:
1917         const AccessMode                        m_mode;
1918         const VkQueueFlags                      m_requiredQueueFlags;
1919 };
1920
1921 } // CopyBufferToImage ns
1922
1923 namespace CopyImageToBuffer
1924 {
1925
1926 class WriteImplementation : public Operation
1927 {
1928 public:
1929         WriteImplementation (OperationContext& context, Resource& resource)
1930                 : m_context                             (context)
1931                 , m_resource                    (resource)
1932                 , m_subresourceRange    (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
1933                 , m_subresourceLayers   (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
1934         {
1935                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_BUFFER);
1936
1937                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1938                 const VkDevice                  device          = m_context.getDevice();
1939                 Allocator&                              allocator       = m_context.getAllocator();
1940                 const VkFormat                  format          = VK_FORMAT_R8G8B8A8_UNORM;
1941                 const deUint32                  pixelSize       = tcu::getPixelSize(mapVkFormat(format));
1942
1943                 DE_ASSERT((m_resource.getBuffer().size % pixelSize) == 0);
1944                 m_imageExtent = get2DImageExtentWithSize(m_resource.getBuffer().size, pixelSize);
1945
1946                 // Source data staging buffer
1947                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
1948                         vk, device, allocator, makeBufferCreateInfo(m_resource.getBuffer().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
1949
1950                 const Allocation& alloc = m_hostBuffer->getAllocation();
1951                 fillPattern(alloc.getHostPtr(), m_resource.getBuffer().size);
1952                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_resource.getBuffer().size);
1953
1954                 // Source data image
1955                 m_image = de::MovePtr<Image>(new Image(
1956                         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));
1957         }
1958
1959         void recordCommands (const VkCommandBuffer cmdBuffer)
1960         {
1961                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1962                 const VkBufferImageCopy copyRegion      = makeBufferImageCopy(m_subresourceLayers, m_imageExtent);
1963
1964                 // Host buffer -> Image
1965                 {
1966                         const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
1967                                 (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
1968                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1969                                 **m_image, m_subresourceRange);
1970                         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);
1971
1972                         vk.cmdCopyBufferToImage(cmdBuffer, **m_hostBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1973                 }
1974                 // Image -> Resource
1975                 {
1976                         const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
1977                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1978                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1979                                 **m_image, m_subresourceRange);
1980                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &layoutBarrier);
1981
1982                         vk.cmdCopyImageToBuffer(cmdBuffer, **m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resource.getBuffer().handle, 1u, &copyRegion);
1983                 }
1984         }
1985
1986         SyncInfo getSyncInfo (void) const
1987         {
1988                 const SyncInfo syncInfo =
1989                 {
1990                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
1991                         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags                        accessMask;
1992                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
1993                 };
1994                 return syncInfo;
1995         }
1996
1997         Data getData (void) const
1998         {
1999                 return getHostBufferData(m_context, *m_hostBuffer, m_resource.getBuffer().size);
2000         }
2001
2002 private:
2003         OperationContext&                               m_context;
2004         Resource&                                               m_resource;
2005         const VkImageSubresourceRange   m_subresourceRange;
2006         const VkImageSubresourceLayers  m_subresourceLayers;
2007         de::MovePtr<Buffer>                             m_hostBuffer;
2008         de::MovePtr<Image>                              m_image;
2009         VkExtent3D                                              m_imageExtent;
2010 };
2011
2012 class ReadImplementation : public Operation
2013 {
2014 public:
2015         ReadImplementation (OperationContext& context, Resource& resource)
2016                 : m_context             (context)
2017                 , m_resource    (resource)
2018                 , m_bufferSize  (getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent))
2019         {
2020                 DE_ASSERT(m_resource.getType() == RESOURCE_TYPE_IMAGE);
2021
2022                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
2023                 const VkDevice                  device          = m_context.getDevice();
2024                 Allocator&                              allocator       = m_context.getAllocator();
2025
2026                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
2027                         vk, device, allocator, makeBufferCreateInfo(m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
2028
2029                 const Allocation& alloc = m_hostBuffer->getAllocation();
2030                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_bufferSize));
2031                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_bufferSize);
2032         }
2033
2034         void recordCommands (const VkCommandBuffer cmdBuffer)
2035         {
2036                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
2037                 const VkBufferImageCopy copyRegion      = makeBufferImageCopy(m_resource.getImage().subresourceLayers, m_resource.getImage().extent);
2038
2039                 vk.cmdCopyImageToBuffer(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_hostBuffer, 1u, &copyRegion);
2040         }
2041
2042         SyncInfo getSyncInfo (void) const
2043         {
2044                 const SyncInfo syncInfo =
2045                 {
2046                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
2047                         VK_ACCESS_TRANSFER_READ_BIT,                    // VkAccessFlags                        accessMask;
2048                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout                        imageLayout;
2049                 };
2050                 return syncInfo;
2051         }
2052
2053         Data getData (void) const
2054         {
2055                 return getHostBufferData(m_context, *m_hostBuffer, m_bufferSize);
2056         }
2057
2058 private:
2059         OperationContext&               m_context;
2060         Resource&                               m_resource;
2061         de::MovePtr<Buffer>             m_hostBuffer;
2062         const VkDeviceSize              m_bufferSize;
2063 };
2064
2065 class Support : public OperationSupport
2066 {
2067 public:
2068         Support (const ResourceDescription& resourceDesc, const AccessMode mode)
2069                 : m_mode                                (mode)
2070                 , m_requiredQueueFlags  (resourceDesc.type == RESOURCE_TYPE_IMAGE && isDepthStencilFormat(resourceDesc.imageFormat) ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_TRANSFER_BIT)
2071         {
2072                 DE_ASSERT(m_mode == ACCESS_MODE_READ || m_mode == ACCESS_MODE_WRITE);
2073                 DE_ASSERT(m_mode == ACCESS_MODE_READ || resourceDesc.type != RESOURCE_TYPE_IMAGE);
2074                 DE_ASSERT(m_mode == ACCESS_MODE_WRITE || resourceDesc.type != RESOURCE_TYPE_BUFFER);
2075         }
2076
2077         deUint32 getResourceUsageFlags (void) const
2078         {
2079                 if (m_mode == ACCESS_MODE_READ)
2080                         return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
2081                 else
2082                         return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2083         }
2084
2085         VkQueueFlags getQueueFlags (void) const
2086         {
2087                 return m_requiredQueueFlags;
2088         }
2089
2090         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2091         {
2092                 if (m_mode == ACCESS_MODE_READ)
2093                         return de::MovePtr<Operation>(new ReadImplementation(context, resource));
2094                 else
2095                         return de::MovePtr<Operation>(new WriteImplementation(context, resource));
2096         }
2097
2098 private:
2099         const AccessMode                        m_mode;
2100         const VkQueueFlags                      m_requiredQueueFlags;
2101 };
2102
2103 } // CopyImageToBuffer ns
2104
2105 namespace ClearImage
2106 {
2107
2108 enum ClearMode
2109 {
2110         CLEAR_MODE_COLOR,
2111         CLEAR_MODE_DEPTH_STENCIL,
2112 };
2113
2114 class Implementation : public Operation
2115 {
2116 public:
2117         Implementation (OperationContext& context, Resource& resource, const ClearMode mode)
2118                 : m_context             (context)
2119                 , m_resource    (resource)
2120                 , m_clearValue  (makeClearValue(m_resource.getImage().format))
2121                 , m_mode                (mode)
2122         {
2123                 const VkDeviceSize                      size            = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
2124                 const VkExtent3D&                       extent          = m_resource.getImage().extent;
2125                 const VkFormat                          format          = m_resource.getImage().format;
2126                 const tcu::TextureFormat        texFormat       = mapVkFormat(format);
2127
2128                 m_data.resize(static_cast<std::size_t>(size));
2129                 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
2130                 clearPixelBuffer(imagePixels, m_clearValue);
2131         }
2132
2133         void recordCommands (const VkCommandBuffer cmdBuffer)
2134         {
2135                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
2136
2137                 const VkImageMemoryBarrier layoutBarrier = makeImageMemoryBarrier(
2138                         (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
2139                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2140                         m_resource.getImage().handle, m_resource.getImage().subresourceRange);
2141
2142                 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);
2143
2144                 if (m_mode == CLEAR_MODE_COLOR)
2145                         vk.cmdClearColorImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.color, 1u, &m_resource.getImage().subresourceRange);
2146                 else
2147                         vk.cmdClearDepthStencilImage(cmdBuffer, m_resource.getImage().handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.depthStencil, 1u, &m_resource.getImage().subresourceRange);
2148         }
2149
2150         SyncInfo getSyncInfo (void) const
2151         {
2152                 const SyncInfo syncInfo =
2153                 {
2154                         VK_PIPELINE_STAGE_TRANSFER_BIT,                 // VkPipelineStageFlags         stageMask;
2155                         VK_ACCESS_TRANSFER_WRITE_BIT,                   // VkAccessFlags                        accessMask;
2156                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout                        imageLayout;
2157                 };
2158                 return syncInfo;
2159         }
2160
2161         Data getData (void) const
2162         {
2163                 const Data data =
2164                 {
2165                         m_data.size(),          // std::size_t          size;
2166                         &m_data[0],                     // const deUint8*       data;
2167                 };
2168                 return data;
2169         }
2170
2171 private:
2172         OperationContext&               m_context;
2173         Resource&                               m_resource;
2174         std::vector<deUint8>    m_data;
2175         const VkClearValue              m_clearValue;
2176         const ClearMode                 m_mode;
2177 };
2178
2179 class Support : public OperationSupport
2180 {
2181 public:
2182         Support (const ResourceDescription& resourceDesc, const ClearMode mode)
2183                 : m_resourceDesc        (resourceDesc)
2184                 , m_mode                        (mode)
2185         {
2186                 DE_ASSERT(m_mode == CLEAR_MODE_COLOR || m_mode == CLEAR_MODE_DEPTH_STENCIL);
2187                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2188                 DE_ASSERT(m_resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT || (m_mode != CLEAR_MODE_COLOR));
2189                 DE_ASSERT((m_resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) || (m_mode != CLEAR_MODE_DEPTH_STENCIL));
2190         }
2191
2192         deUint32 getResourceUsageFlags (void) const
2193         {
2194                 return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2195         }
2196
2197         VkQueueFlags getQueueFlags (void) const
2198         {
2199                 if (m_mode == CLEAR_MODE_COLOR)
2200                         return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
2201                 else
2202                         return VK_QUEUE_GRAPHICS_BIT;
2203         }
2204
2205         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2206         {
2207                 return de::MovePtr<Operation>(new Implementation(context, resource, m_mode));
2208         }
2209
2210 private:
2211         const ResourceDescription       m_resourceDesc;
2212         const ClearMode                         m_mode;
2213 };
2214
2215 } // ClearImage ns
2216
2217 namespace Draw
2218 {
2219
2220 enum DrawCall
2221 {
2222         DRAW_CALL_DRAW,
2223         DRAW_CALL_DRAW_INDEXED,
2224         DRAW_CALL_DRAW_INDIRECT,
2225         DRAW_CALL_DRAW_INDEXED_INDIRECT,
2226 };
2227
2228 //! A write operation that is a result of drawing to an image.
2229 //! \todo Add support for depth/stencil too?
2230 class Implementation : public Operation
2231 {
2232 public:
2233         Implementation (OperationContext& context, Resource& resource, const DrawCall drawCall)
2234                 : m_context             (context)
2235                 , m_resource    (resource)
2236                 , m_drawCall    (drawCall)
2237                 , m_vertices    (context)
2238         {
2239                 const DeviceInterface&          vk                              = context.getDeviceInterface();
2240                 const VkDevice                          device                  = context.getDevice();
2241                 Allocator&                                      allocator               = context.getAllocator();
2242
2243                 // Indirect buffer
2244
2245                 if (m_drawCall == DRAW_CALL_DRAW_INDIRECT)
2246                 {
2247                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
2248                                 makeBufferCreateInfo(sizeof(VkDrawIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
2249
2250                         const Allocation&                               alloc                           = m_indirectBuffer->getAllocation();
2251                         VkDrawIndirectCommand* const    pIndirectCommand        = static_cast<VkDrawIndirectCommand*>(alloc.getHostPtr());
2252
2253                         pIndirectCommand->vertexCount   = m_vertices.getNumVertices();
2254                         pIndirectCommand->instanceCount = 1u;
2255                         pIndirectCommand->firstVertex   = 0u;
2256                         pIndirectCommand->firstInstance = 0u;
2257
2258                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeof(VkDrawIndirectCommand));
2259                 }
2260                 else if (m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
2261                 {
2262                         m_indirectBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
2263                                 makeBufferCreateInfo(sizeof(VkDrawIndexedIndirectCommand), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), MemoryRequirement::HostVisible));
2264
2265                         const Allocation&                                       alloc                           = m_indirectBuffer->getAllocation();
2266                         VkDrawIndexedIndirectCommand* const     pIndirectCommand        = static_cast<VkDrawIndexedIndirectCommand*>(alloc.getHostPtr());
2267
2268                         pIndirectCommand->indexCount    = m_vertices.getNumIndices();
2269                         pIndirectCommand->instanceCount = 1u;
2270                         pIndirectCommand->firstIndex    = 0u;
2271                         pIndirectCommand->vertexOffset  = 0u;
2272                         pIndirectCommand->firstInstance = 0u;
2273
2274                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeof(VkDrawIndexedIndirectCommand));
2275                 }
2276
2277                 // Resource image is the color attachment
2278
2279                 m_colorFormat                   = m_resource.getImage().format;
2280                 m_colorSubresourceRange = m_resource.getImage().subresourceRange;
2281                 m_colorImage                    = m_resource.getImage().handle;
2282                 m_attachmentExtent              = m_resource.getImage().extent;
2283
2284                 // Pipeline
2285
2286                 m_colorAttachmentView   = makeImageView                                           (vk, device, m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
2287                 m_renderPass                    = makeRenderPass                                          (vk, device, m_colorFormat);
2288                 m_framebuffer                   = makeFramebuffer                                         (vk, device, *m_renderPass, *m_colorAttachmentView, m_attachmentExtent.width, m_attachmentExtent.height, 1u);
2289                 m_pipelineLayout                = makePipelineLayoutWithoutDescriptors(vk, device);
2290
2291                 GraphicsPipelineBuilder pipelineBuilder;
2292                 pipelineBuilder
2293                         .setRenderSize                                  (tcu::IVec2(m_attachmentExtent.width, m_attachmentExtent.height))
2294                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
2295                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get("draw_vert"), DE_NULL)
2296                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get("draw_frag"), DE_NULL);
2297
2298                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
2299
2300                 // Set expected draw values
2301
2302                 m_expectedData.resize(static_cast<size_t>(getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent)));
2303                 tcu::PixelBufferAccess imagePixels(mapVkFormat(m_colorFormat), m_attachmentExtent.width, m_attachmentExtent.height, m_attachmentExtent.depth, &m_expectedData[0]);
2304                 clearPixelBuffer(imagePixels, makeClearValue(m_colorFormat));
2305         }
2306
2307         void recordCommands (const VkCommandBuffer cmdBuffer)
2308         {
2309                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
2310
2311                 // Change color attachment image layout
2312                 {
2313                         const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
2314                                 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2315                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2316                                 m_colorImage, m_colorSubresourceRange);
2317
2318                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
2319                                 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
2320                 }
2321
2322                 {
2323                         const VkRect2D renderArea = {
2324                                 makeOffset2D(0, 0),
2325                                 makeExtent2D(m_attachmentExtent.width, m_attachmentExtent.height),
2326                         };
2327                         const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2328
2329                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
2330                 }
2331
2332                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
2333                 {
2334                         const VkDeviceSize      vertexBufferOffset      = 0ull;
2335                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
2336                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
2337                 }
2338
2339                 if (m_drawCall == DRAW_CALL_DRAW_INDEXED || m_drawCall == DRAW_CALL_DRAW_INDEXED_INDIRECT)
2340                         vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
2341
2342                 switch (m_drawCall)
2343                 {
2344                         case DRAW_CALL_DRAW:
2345                                 vk.cmdDraw(cmdBuffer, m_vertices.getNumVertices(), 1u, 0u, 0u);
2346                                 break;
2347
2348                         case DRAW_CALL_DRAW_INDEXED:
2349                                 vk.cmdDrawIndexed(cmdBuffer, m_vertices.getNumIndices(), 1u, 0u, 0, 0u);
2350                                 break;
2351
2352                         case DRAW_CALL_DRAW_INDIRECT:
2353                                 vk.cmdDrawIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
2354                                 break;
2355
2356                         case DRAW_CALL_DRAW_INDEXED_INDIRECT:
2357                                 vk.cmdDrawIndexedIndirect(cmdBuffer, **m_indirectBuffer, 0u, 1u, 0u);
2358                                 break;
2359                 }
2360
2361                 endRenderPass(vk, cmdBuffer);
2362         }
2363
2364         SyncInfo getSyncInfo (void) const
2365         {
2366                 const SyncInfo syncInfo =
2367                 {
2368                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,          // VkPipelineStageFlags         stageMask;
2369                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags                        accessMask;
2370                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        imageLayout;
2371                 };
2372                 return syncInfo;
2373         }
2374
2375         Data getData (void) const
2376         {
2377                 const Data data =
2378                 {
2379                         m_expectedData.size(),          // std::size_t          size;
2380                         &m_expectedData[0],                     // const deUint8*       data;
2381                 };
2382                 return data;
2383         }
2384
2385 private:
2386         OperationContext&                       m_context;
2387         Resource&                                       m_resource;
2388         const DrawCall                          m_drawCall;
2389         const VertexGrid                        m_vertices;
2390         std::vector<deUint8>            m_expectedData;
2391         de::MovePtr<Buffer>                     m_indirectBuffer;
2392         VkFormat                                        m_colorFormat;
2393         VkImage                                         m_colorImage;
2394         Move<VkImageView>                       m_colorAttachmentView;
2395         VkImageSubresourceRange         m_colorSubresourceRange;
2396         VkExtent3D                                      m_attachmentExtent;
2397         Move<VkRenderPass>                      m_renderPass;
2398         Move<VkFramebuffer>                     m_framebuffer;
2399         Move<VkPipelineLayout>          m_pipelineLayout;
2400         Move<VkPipeline>                        m_pipeline;
2401 };
2402
2403 template<typename T, std::size_t N>
2404 std::string toString (const T (&values)[N])
2405 {
2406         std::ostringstream str;
2407         for (std::size_t i = 0; i < N; ++i)
2408                 str << (i != 0 ? ", " : "") << values[i];
2409         return str.str();
2410 }
2411
2412 class Support : public OperationSupport
2413 {
2414 public:
2415         Support (const ResourceDescription& resourceDesc, const DrawCall drawCall)
2416                 : m_resourceDesc        (resourceDesc)
2417                 , m_drawCall            (drawCall)
2418         {
2419                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE && m_resourceDesc.imageType == VK_IMAGE_TYPE_2D);
2420                 DE_ASSERT(!isDepthStencilFormat(m_resourceDesc.imageFormat));
2421         }
2422
2423         void initPrograms (SourceCollections& programCollection) const
2424         {
2425                 // Vertex
2426                 {
2427                         std::ostringstream src;
2428                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2429                                 << "\n"
2430                                 << "layout(location = 0) in vec4 v_in_position;\n"
2431                                 << "\n"
2432                                 << "out " << s_perVertexBlock << ";\n"
2433                                 << "\n"
2434                                 << "void main (void)\n"
2435                                 << "{\n"
2436                                 << "    gl_Position = v_in_position;\n"
2437                                 << "}\n";
2438
2439                         programCollection.glslSources.add("draw_vert") << glu::VertexSource(src.str());
2440                 }
2441
2442                 // Fragment
2443                 {
2444                         const VkClearValue      clearValue              = makeClearValue(m_resourceDesc.imageFormat);
2445                         const bool                      isIntegerFormat = isIntFormat(m_resourceDesc.imageFormat) || isUintFormat(m_resourceDesc.imageFormat);
2446                         const std::string       colorType               = (isIntegerFormat ? "uvec4" : "vec4");
2447
2448                         std::ostringstream src;
2449                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
2450                                 << "\n"
2451                                 << "layout(location = 0) out " << colorType << " o_color;\n"
2452                                 << "\n"
2453                                 << "void main (void)\n"
2454                                 << "{\n"
2455                                 << "    o_color = " << colorType << "(" << (isIntegerFormat ? toString(clearValue.color.uint32) : toString(clearValue.color.float32)) << ");\n"
2456                                 << "}\n";
2457
2458                         programCollection.glslSources.add("draw_frag") << glu::FragmentSource(src.str());
2459                 }
2460         }
2461
2462         deUint32 getResourceUsageFlags (void) const
2463         {
2464                 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
2465         }
2466
2467         VkQueueFlags getQueueFlags (void) const
2468         {
2469                 return VK_QUEUE_GRAPHICS_BIT;
2470         }
2471
2472         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2473         {
2474                 return de::MovePtr<Operation>(new Implementation(context, resource, m_drawCall));
2475         }
2476
2477 private:
2478         const ResourceDescription       m_resourceDesc;
2479         const DrawCall                          m_drawCall;
2480 };
2481
2482 } // Draw ns
2483
2484 namespace ClearAttachments
2485 {
2486
2487 class Implementation : public Operation
2488 {
2489 public:
2490         Implementation (OperationContext& context, Resource& resource)
2491                 : m_context             (context)
2492                 , m_resource    (resource)
2493                 , m_clearValue  (makeClearValue(m_resource.getImage().format))
2494         {
2495                 const DeviceInterface&          vk                              = context.getDeviceInterface();
2496                 const VkDevice                          device                  = context.getDevice();
2497
2498                 const VkDeviceSize                      size            = getPixelBufferSize(m_resource.getImage().format, m_resource.getImage().extent);
2499                 const VkExtent3D&                       extent          = m_resource.getImage().extent;
2500                 const VkFormat                          format          = m_resource.getImage().format;
2501                 const tcu::TextureFormat        texFormat       = mapVkFormat(format);
2502                 const SyncInfo                          syncInfo        = getSyncInfo();
2503
2504                 m_data.resize(static_cast<std::size_t>(size));
2505                 tcu::PixelBufferAccess imagePixels(texFormat, extent.width, extent.height, extent.depth, &m_data[0]);
2506                 clearPixelBuffer(imagePixels, m_clearValue);
2507
2508                 m_attachmentView = makeImageView(vk, device, m_resource.getImage().handle, getImageViewType(m_resource.getImage().imageType), m_resource.getImage().format, m_resource.getImage().subresourceRange);
2509
2510                 const VkAttachmentDescription colorAttachmentDescription =
2511                 {
2512                         (VkAttachmentDescriptionFlags)0,        // VkAttachmentDescriptionFlags         flags;
2513                         m_resource.getImage().format,           // VkFormat                                                     format;
2514                         VK_SAMPLE_COUNT_1_BIT,                          // VkSampleCountFlagBits                        samples;
2515                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,        // VkAttachmentLoadOp                           loadOp;
2516                         VK_ATTACHMENT_STORE_OP_STORE,           // VkAttachmentStoreOp                          storeOp;
2517                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,        // VkAttachmentLoadOp                           stencilLoadOp;
2518                         VK_ATTACHMENT_STORE_OP_STORE,           // VkAttachmentStoreOp                          stencilStoreOp;
2519                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                                        initialLayout;
2520                         syncInfo.imageLayout                            // VkImageLayout                                        finalLayout;
2521                 };
2522
2523                 const VkAttachmentReference colorAttachmentReference =
2524                 {
2525                         0u,                                             // deUint32                     attachment;
2526                         syncInfo.imageLayout    // VkImageLayout        layout;
2527                 };
2528
2529                 const VkAttachmentReference depthStencilAttachmentReference =
2530                 {
2531                         0u,                                             // deUint32                     attachment;
2532                         syncInfo.imageLayout    // VkImageLayout        layout;
2533                 };
2534
2535                 VkSubpassDescription subpassDescription =
2536                 {
2537                         (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
2538                         VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
2539                         0u,                                                                     // deUint32                                                     inputAttachmentCount;
2540                         DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
2541                         0u,                                                                     // deUint32                                                     colorAttachmentCount;
2542                         DE_NULL,                                                        // const VkAttachmentReference*         pColorAttachments;
2543                         DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
2544                         DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
2545                         0u,                                                                     // deUint32                                                     preserveAttachmentCount;
2546                         DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
2547                 };
2548
2549                 switch (m_resource.getImage().subresourceRange.aspectMask)
2550                 {
2551                         case VK_IMAGE_ASPECT_COLOR_BIT:
2552                                 subpassDescription.colorAttachmentCount = 1u;
2553                                 subpassDescription.pColorAttachments    = &colorAttachmentReference;
2554                         break;
2555                         case VK_IMAGE_ASPECT_STENCIL_BIT:
2556                         case VK_IMAGE_ASPECT_DEPTH_BIT:
2557                                 subpassDescription.pDepthStencilAttachment = &depthStencilAttachmentReference;
2558                         break;
2559                         default:
2560                                 DE_ASSERT(0);
2561                         break;
2562                 }
2563
2564                 const VkRenderPassCreateInfo renderPassInfo =
2565                 {
2566                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType;
2567                         DE_NULL,                                                                        // const void*                                          pNext;
2568                         (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags;
2569                         1u,                                                                                     // deUint32                                                     attachmentCount;
2570                         &colorAttachmentDescription,                            // const VkAttachmentDescription*       pAttachments;
2571                         1u,                                                                                     // deUint32                                                     subpassCount;
2572                         &subpassDescription,                                            // const VkSubpassDescription*          pSubpasses;
2573                         0u,                                                                                     // deUint32                                                     dependencyCount;
2574                         DE_NULL                                                                         // const VkSubpassDependency*           pDependencies;
2575                 };
2576
2577                 m_renderPass    = createRenderPass(vk, device, &renderPassInfo);
2578                 m_frameBuffer   = makeFramebuffer(vk, device, *m_renderPass, *m_attachmentView, m_resource.getImage().extent.width, m_resource.getImage().extent.height, 1u);
2579         }
2580
2581         void recordCommands (const VkCommandBuffer cmdBuffer)
2582         {
2583                 const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
2584                 const VkRenderPassBeginInfo     renderPassBeginInfo             =
2585                 {
2586                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
2587                         DE_NULL,                                                                                                // const void*                  pNext;
2588                         *m_renderPass,                                                                                  // VkRenderPass                 renderPass;
2589                         *m_frameBuffer,                                                                                 // VkFramebuffer                framebuffer;
2590                         {
2591                                 { 0, 0 },                                                                                       // VkOffset2D                   offset;
2592                                 {
2593                                         m_resource.getImage().extent.width,                             // deUint32                             width;
2594                                         m_resource.getImage().extent.height                             // deUint32                             height;
2595                                 }                                                                                                       // VkExtent2D                   extent;
2596                         },                                                                                                              // VkRect2D                             renderArea;
2597                         1u,                                                                                                             // deUint32                             clearValueCount;
2598                         &m_clearValue                                                                                   // const VkClearValue*  pClearValues;
2599                 };
2600
2601                 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2602
2603                 const VkClearAttachment clearAttachment =
2604                 {
2605                         m_resource.getImage().subresourceRange.aspectMask,      // VkImageAspectFlags   aspectMask;
2606                         0,                                                                                                      // deUint32                             colorAttachment;
2607                         m_clearValue                                                                            // VkClearValue                 clearValue;
2608                 };
2609
2610                 const VkRect2D                  rect2D                  =
2611                 {
2612                         { 0u, 0u, },                                                                                                                                    //      VkOffset2D      offset;
2613                         { m_resource.getImage().extent.width, m_resource.getImage().extent.height },    //      VkExtent2D      extent;
2614                 };
2615
2616                 const VkClearRect               clearRect               =
2617                 {
2618                         rect2D,                                                                                         // VkRect2D     rect;
2619                         0u,                                                                                                     // deUint32     baseArrayLayer;
2620                         m_resource.getImage().subresourceLayers.layerCount      // deUint32     layerCount;
2621                 };
2622
2623                 vk.cmdClearAttachments(cmdBuffer, 1, &clearAttachment, 1, &clearRect);
2624
2625                 vk.cmdEndRenderPass(cmdBuffer);
2626         }
2627
2628         SyncInfo getSyncInfo (void) const
2629         {
2630                 SyncInfo syncInfo;
2631                 syncInfo.stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2632
2633                 switch (m_resource.getImage().subresourceRange.aspectMask)
2634                 {
2635                         case VK_IMAGE_ASPECT_COLOR_BIT:
2636                                 syncInfo.accessMask             = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2637                                 syncInfo.imageLayout    = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2638                         break;
2639                         case VK_IMAGE_ASPECT_STENCIL_BIT:
2640                         case VK_IMAGE_ASPECT_DEPTH_BIT:
2641                                 syncInfo.accessMask             = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2642                                 syncInfo.imageLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2643                         break;
2644                         default:
2645                                 DE_ASSERT(0);
2646                         break;
2647                 }
2648
2649                 return syncInfo;
2650         }
2651
2652         Data getData (void) const
2653         {
2654                 const Data data =
2655                 {
2656                         m_data.size(),  // std::size_t          size;
2657                         &m_data[0],             // const deUint8*       data;
2658                 };
2659                 return data;
2660         }
2661
2662 private:
2663         OperationContext&               m_context;
2664         Resource&                               m_resource;
2665         std::vector<deUint8>    m_data;
2666         const VkClearValue              m_clearValue;
2667         Move<VkImageView>               m_attachmentView;
2668         Move<VkRenderPass>              m_renderPass;
2669         Move<VkFramebuffer>             m_frameBuffer;
2670 };
2671
2672 class Support : public OperationSupport
2673 {
2674 public:
2675         Support (const ResourceDescription& resourceDesc)
2676                 : m_resourceDesc (resourceDesc)
2677         {
2678                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
2679         }
2680
2681         deUint32 getResourceUsageFlags (void) const
2682         {
2683                 switch (m_resourceDesc.imageAspect)
2684                 {
2685                         case VK_IMAGE_ASPECT_COLOR_BIT:
2686                                 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
2687                         case VK_IMAGE_ASPECT_STENCIL_BIT:
2688                         case VK_IMAGE_ASPECT_DEPTH_BIT:
2689                                 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
2690                         default:
2691                                 DE_ASSERT(0);
2692                 }
2693                 return 0u;
2694         }
2695
2696         VkQueueFlags getQueueFlags (void) const
2697         {
2698                 return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
2699         }
2700
2701         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
2702         {
2703                 return de::MovePtr<Operation>(new Implementation(context, resource));
2704         }
2705
2706 private:
2707         const ResourceDescription       m_resourceDesc;
2708 };
2709
2710 } // ClearAttachments
2711
2712 namespace IndirectBuffer
2713 {
2714
2715 class GraphicsPipeline : public Pipeline
2716 {
2717 public:
2718         GraphicsPipeline (OperationContext&                             context,
2719                                           const ResourceType                    resourceType,
2720                                           const VkBuffer                                indirectBuffer,
2721                                           const std::string&                    shaderPrefix,
2722                                           const VkDescriptorSetLayout   descriptorSetLayout)
2723                 : m_resourceType        (resourceType)
2724                 , m_indirectBuffer      (indirectBuffer)
2725                 , m_vertices            (context)
2726         {
2727                 const DeviceInterface&          vk                              = context.getDeviceInterface();
2728                 const VkDevice                          device                  = context.getDevice();
2729                 Allocator&                                      allocator               = context.getAllocator();
2730
2731                 // Color attachment
2732
2733                 m_colorFormat                                   = VK_FORMAT_R8G8B8A8_UNORM;
2734                 m_colorImageSubresourceRange    = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2735                 m_colorImageExtent                              = makeExtent3D(16u, 16u, 1u);
2736                 m_colorAttachmentImage                  = de::MovePtr<Image>(new Image(vk, device, allocator,
2737                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
2738                         MemoryRequirement::Any));
2739
2740                 // Pipeline
2741
2742                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
2743                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
2744                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height, 1u);
2745                 m_pipelineLayout                = makePipelineLayout(vk, device, descriptorSetLayout);
2746
2747                 GraphicsPipelineBuilder pipelineBuilder;
2748                 pipelineBuilder
2749                         .setRenderSize                                  (tcu::IVec2(m_colorImageExtent.width, m_colorImageExtent.height))
2750                         .setVertexInputSingleAttribute  (m_vertices.getVertexFormat(), m_vertices.getVertexStride())
2751                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get(shaderPrefix + "vert"), DE_NULL)
2752                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get(shaderPrefix + "frag"), DE_NULL);
2753
2754                 m_pipeline = pipelineBuilder.build(vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
2755         }
2756
2757         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
2758         {
2759                 const DeviceInterface&  vk      = context.getDeviceInterface();
2760
2761                 // Change color attachment image layout
2762                 {
2763                         const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
2764                                 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2765                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2766                                 **m_colorAttachmentImage, m_colorImageSubresourceRange);
2767
2768                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
2769                                 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
2770                 }
2771
2772                 {
2773                         const VkRect2D renderArea = {
2774                                 makeOffset2D(0, 0),
2775                                 makeExtent2D(m_colorImageExtent.width, m_colorImageExtent.height),
2776                         };
2777                         const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2778
2779                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
2780                 }
2781
2782                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
2783                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2784                 {
2785                         const VkDeviceSize      vertexBufferOffset      = 0ull;
2786                         const VkBuffer          vertexBuffer            = m_vertices.getVertexBuffer();
2787                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
2788                 }
2789
2790                 switch (m_resourceType)
2791                 {
2792                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
2793                                 vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
2794                                 break;
2795
2796                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
2797                                 vk.cmdBindIndexBuffer(cmdBuffer, m_vertices.getIndexBuffer(), 0u, m_vertices.getIndexType());
2798                                 vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer, 0u, 1u, 0u);
2799                                 break;
2800
2801                         default:
2802                                 DE_ASSERT(0);
2803                                 break;
2804                 }
2805                 endRenderPass(vk, cmdBuffer);
2806         }
2807
2808 private:
2809         const ResourceType                      m_resourceType;
2810         const VkBuffer                          m_indirectBuffer;
2811         const VertexGrid                        m_vertices;
2812         VkFormat                                        m_colorFormat;
2813         de::MovePtr<Image>                      m_colorAttachmentImage;
2814         Move<VkImageView>                       m_colorAttachmentView;
2815         VkExtent3D                                      m_colorImageExtent;
2816         VkImageSubresourceRange         m_colorImageSubresourceRange;
2817         Move<VkRenderPass>                      m_renderPass;
2818         Move<VkFramebuffer>                     m_framebuffer;
2819         Move<VkPipelineLayout>          m_pipelineLayout;
2820         Move<VkPipeline>                        m_pipeline;
2821 };
2822
2823 class ComputePipeline : public Pipeline
2824 {
2825 public:
2826         ComputePipeline (OperationContext&                              context,
2827                                          const VkBuffer                                 indirectBuffer,
2828                                          const std::string&                             shaderPrefix,
2829                                          const VkDescriptorSetLayout    descriptorSetLayout)
2830                 : m_indirectBuffer      (indirectBuffer)
2831         {
2832                 const DeviceInterface&  vk              = context.getDeviceInterface();
2833                 const VkDevice                  device  = context.getDevice();
2834
2835                 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, context.getBinaryCollection().get(shaderPrefix + "comp"), (VkShaderModuleCreateFlags)0));
2836
2837                 m_pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout);
2838                 m_pipeline               = makeComputePipeline(vk, device, *m_pipelineLayout, *shaderModule, DE_NULL, context.getPipelineCacheData());
2839         }
2840
2841         void recordCommands (OperationContext& context, const VkCommandBuffer cmdBuffer, const VkDescriptorSet descriptorSet)
2842         {
2843                 const DeviceInterface&  vk      = context.getDeviceInterface();
2844
2845                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline);
2846                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2847                 vk.cmdDispatchIndirect(cmdBuffer, m_indirectBuffer, 0u);
2848         }
2849
2850 private:
2851         const VkBuffer                          m_indirectBuffer;
2852         Move<VkPipelineLayout>          m_pipelineLayout;
2853         Move<VkPipeline>                        m_pipeline;
2854 };
2855
2856 //! Read indirect buffer by executing an indirect draw or dispatch command.
2857 class ReadImplementation : public Operation
2858 {
2859 public:
2860         ReadImplementation (OperationContext& context, Resource& resource)
2861                 : m_context                             (context)
2862                 , m_resource                    (resource)
2863                 , m_stage                               (resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT)
2864                 , m_pipelineStage               (pipelineStageFlagsFromShaderStageFlagBits(m_stage))
2865                 , m_hostBufferSizeBytes (sizeof(deUint32))
2866         {
2867                 requireFeaturesForSSBOAccess (m_context, m_stage);
2868
2869                 const DeviceInterface&  vk                      = m_context.getDeviceInterface();
2870                 const VkDevice                  device          = m_context.getDevice();
2871                 Allocator&                              allocator       = m_context.getAllocator();
2872
2873                 m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
2874                         vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
2875
2876                 // Init host buffer data
2877                 {
2878                         const Allocation& alloc = m_hostBuffer->getAllocation();
2879                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(m_hostBufferSizeBytes));
2880                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), static_cast<size_t>(m_hostBufferSizeBytes));
2881                 }
2882
2883                 // Prepare descriptors
2884                 {
2885                         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2886                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_stage)
2887                                 .build(vk, device);
2888
2889                         m_descriptorPool = DescriptorPoolBuilder()
2890                                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2891                                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2892
2893                         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2894
2895                         const VkDescriptorBufferInfo  hostBufferInfo = makeDescriptorBufferInfo(**m_hostBuffer, 0u, m_hostBufferSizeBytes);
2896
2897                         DescriptorSetUpdateBuilder()
2898                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &hostBufferInfo)
2899                                 .update(vk, device);
2900                 }
2901
2902                 // Create pipeline
2903                 m_pipeline = (m_resource.getType() == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH
2904                         ? de::MovePtr<Pipeline>(new ComputePipeline(context, m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout))
2905                         : de::MovePtr<Pipeline>(new GraphicsPipeline(context, m_resource.getType(), m_resource.getBuffer().handle, "read_ib_", *m_descriptorSetLayout)));
2906         }
2907
2908         void recordCommands (const VkCommandBuffer cmdBuffer)
2909         {
2910                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
2911
2912                 m_pipeline->recordCommands(m_context, cmdBuffer, *m_descriptorSet);
2913
2914                 // Insert a barrier so data written by the shader is available to the host
2915                 const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_hostBuffer, 0u, m_hostBufferSizeBytes);
2916                 vk.cmdPipelineBarrier(cmdBuffer, m_pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
2917         }
2918
2919         SyncInfo getSyncInfo (void) const
2920         {
2921                 const SyncInfo syncInfo =
2922                 {
2923                         VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,    // VkPipelineStageFlags         stageMask;
2924                         VK_ACCESS_INDIRECT_COMMAND_READ_BIT,    // VkAccessFlags                        accessMask;
2925                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
2926                 };
2927                 return syncInfo;
2928         }
2929
2930         Data getData (void) const
2931         {
2932                 return getHostBufferData(m_context, *m_hostBuffer, m_hostBufferSizeBytes);
2933         }
2934
2935 private:
2936         OperationContext&                       m_context;
2937         Resource&                                       m_resource;
2938         const VkShaderStageFlagBits     m_stage;
2939         const VkPipelineStageFlags      m_pipelineStage;
2940         const VkDeviceSize                      m_hostBufferSizeBytes;
2941         de::MovePtr<Buffer>                     m_hostBuffer;
2942         Move<VkDescriptorPool>          m_descriptorPool;
2943         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
2944         Move<VkDescriptorSet>           m_descriptorSet;
2945         de::MovePtr<Pipeline>           m_pipeline;
2946 };
2947
2948 //! Prepare indirect buffer for a draw/dispatch call.
2949 class WriteImplementation : public Operation
2950 {
2951 public:
2952         WriteImplementation (OperationContext& context, Resource& resource)
2953                 : m_context                     (context)
2954                 , m_resource            (resource)
2955         {
2956                 switch (m_resource.getType())
2957                 {
2958                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
2959                         {
2960                                 m_drawIndirect.vertexCount              = 6u;
2961                                 m_drawIndirect.instanceCount    = 1u;
2962                                 m_drawIndirect.firstVertex              = 0u;
2963                                 m_drawIndirect.firstInstance    = 0u;
2964
2965                                 m_indirectData                                  = reinterpret_cast<deUint32*>(&m_drawIndirect);
2966                                 m_expectedValue                                 = 6u;
2967                         }
2968                         break;
2969
2970                         case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
2971                         {
2972                                 m_drawIndexedIndirect.indexCount        = 6u;
2973                                 m_drawIndexedIndirect.instanceCount     = 1u;
2974                                 m_drawIndexedIndirect.firstIndex        = 0u;
2975                                 m_drawIndexedIndirect.vertexOffset      = 0u;
2976                                 m_drawIndexedIndirect.firstInstance     = 0u;
2977
2978                                 m_indirectData                                          = reinterpret_cast<deUint32*>(&m_drawIndexedIndirect);
2979                                 m_expectedValue                                         = 6u;
2980                         }
2981                         break;
2982
2983                         case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
2984                         {
2985                                 m_dispatchIndirect.x    = 7u;
2986                                 m_dispatchIndirect.y    = 2u;
2987                                 m_dispatchIndirect.z    = 1u;
2988
2989                                 m_indirectData                  = reinterpret_cast<deUint32*>(&m_dispatchIndirect);
2990                                 m_expectedValue                 = 14u;
2991                         }
2992                         break;
2993
2994                         default:
2995                                 DE_ASSERT(0);
2996                                 break;
2997                 }
2998         }
2999
3000         void recordCommands (const VkCommandBuffer cmdBuffer)
3001         {
3002                 const DeviceInterface&  vk      = m_context.getDeviceInterface();
3003
3004                 vk.cmdUpdateBuffer(cmdBuffer, m_resource.getBuffer().handle, m_resource.getBuffer().offset, m_resource.getBuffer().size, m_indirectData);
3005         }
3006
3007         SyncInfo getSyncInfo (void) const
3008         {
3009                 const SyncInfo syncInfo =
3010                 {
3011                         VK_PIPELINE_STAGE_TRANSFER_BIT,         // VkPipelineStageFlags         stageMask;
3012                         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags                        accessMask;
3013                         VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout                        imageLayout;
3014                 };
3015                 return syncInfo;
3016         }
3017
3018         Data getData (void) const
3019         {
3020                 const Data data =
3021                 {
3022                         sizeof(deUint32),                                                                       // std::size_t          size;
3023                         reinterpret_cast<const deUint8*>(&m_expectedValue),     // const deUint8*       data;
3024                 };
3025                 return data;
3026         }
3027
3028 private:
3029         OperationContext&                               m_context;
3030         Resource&                                               m_resource;
3031         VkDrawIndirectCommand                   m_drawIndirect;
3032         VkDrawIndexedIndirectCommand    m_drawIndexedIndirect;
3033         VkDispatchIndirectCommand               m_dispatchIndirect;
3034         deUint32*                                               m_indirectData;
3035         deUint32                                                m_expectedValue;        //! Side-effect value expected to be computed by a read (draw/dispatch) command.
3036 };
3037
3038 class ReadSupport : public OperationSupport
3039 {
3040 public:
3041         ReadSupport (const ResourceDescription& resourceDesc)
3042                 : m_resourceDesc        (resourceDesc)
3043         {
3044                 DE_ASSERT(isIndirectBuffer(m_resourceDesc.type));
3045         }
3046
3047         void initPrograms (SourceCollections& programCollection) const
3048         {
3049                 std::ostringstream decl;
3050                 decl << "layout(set = 0, binding = 0, std140) coherent buffer Data {\n"
3051                          << "    uint value;\n"
3052                          << "} sb_out;\n";
3053
3054                 std::ostringstream main;
3055                 main << "    atomicAdd(sb_out.value, 1u);\n";
3056
3057                 // Vertex
3058                 {
3059                         std::ostringstream src;
3060                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
3061                                 << "\n"
3062                                 << "layout(location = 0) in vec4 v_in_position;\n"
3063                                 << "\n"
3064                                 << "out " << s_perVertexBlock << ";\n"
3065                                 << "\n"
3066                                 << decl.str()
3067                                 << "\n"
3068                                 << "void main (void)\n"
3069                                 << "{\n"
3070                                 << "    gl_Position = v_in_position;\n"
3071                                 << main.str()
3072                                 << "}\n";
3073
3074                         programCollection.glslSources.add("read_ib_vert") << glu::VertexSource(src.str());
3075                 }
3076
3077                 // Fragment
3078                 {
3079                         std::ostringstream src;
3080                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
3081                                 << "\n"
3082                                 << "layout(location = 0) out vec4 o_color;\n"
3083                                 << "\n"
3084                                 << "void main (void)\n"
3085                                 << "{\n"
3086                                 << "    o_color = vec4(1.0);\n"
3087                                 << "}\n";
3088
3089                         programCollection.glslSources.add("read_ib_frag") << glu::FragmentSource(src.str());
3090                 }
3091
3092                 // Compute
3093                 {
3094                         std::ostringstream src;
3095                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
3096                                 << "\n"
3097                                 << "layout(local_size_x = 1) in;\n"
3098                                 << "\n"
3099                                 << decl.str()
3100                                 << "\n"
3101                                 << "void main (void)\n"
3102                                 << "{\n"
3103                                 << main.str()
3104                                 << "}\n";
3105
3106                         programCollection.glslSources.add("read_ib_comp") << glu::ComputeSource(src.str());
3107                 }
3108         }
3109
3110         deUint32 getResourceUsageFlags (void) const
3111         {
3112                 return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
3113         }
3114
3115         VkQueueFlags getQueueFlags (void) const
3116         {
3117                 return (m_resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT);
3118         }
3119
3120         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3121         {
3122                 return de::MovePtr<Operation>(new ReadImplementation(context, resource));
3123         }
3124
3125 private:
3126         const ResourceDescription       m_resourceDesc;
3127 };
3128
3129
3130 class WriteSupport : public OperationSupport
3131 {
3132 public:
3133         WriteSupport (const ResourceDescription& resourceDesc)
3134         {
3135                 DE_ASSERT(isIndirectBuffer(resourceDesc.type));
3136                 DE_UNREF(resourceDesc);
3137         }
3138
3139         deUint32 getResourceUsageFlags (void) const
3140         {
3141                 return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3142         }
3143
3144         VkQueueFlags getQueueFlags (void) const
3145         {
3146                 return VK_QUEUE_TRANSFER_BIT;
3147         }
3148
3149         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3150         {
3151                 return de::MovePtr<Operation>(new WriteImplementation(context, resource));
3152         }
3153 };
3154
3155 } // IndirectBuffer ns
3156
3157 namespace VertexInput
3158 {
3159
3160 class Implementation : public Operation
3161 {
3162 public:
3163         Implementation (OperationContext& context, Resource& resource)
3164                 : m_context             (context)
3165                 , m_resource    (resource)
3166         {
3167                 requireFeaturesForSSBOAccess (m_context, VK_SHADER_STAGE_VERTEX_BIT);
3168
3169                 const DeviceInterface&          vk                              = context.getDeviceInterface();
3170                 const VkDevice                          device                  = context.getDevice();
3171                 Allocator&                                      allocator               = context.getAllocator();
3172                 const VkDeviceSize                      dataSizeBytes   = m_resource.getBuffer().size;
3173
3174                 m_outputBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
3175                         makeBufferCreateInfo(dataSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible));
3176
3177                 {
3178                         const Allocation& alloc = m_outputBuffer->getAllocation();
3179                         deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(dataSizeBytes));
3180                         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), dataSizeBytes);
3181                 }
3182
3183                 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
3184                         .addSingleBinding       (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
3185                         .build                          (vk, device);
3186
3187                 m_descriptorPool = DescriptorPoolBuilder()
3188                         .addType        (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3189                         .build          (vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
3190
3191                 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
3192
3193                 const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, dataSizeBytes);
3194                 DescriptorSetUpdateBuilder()
3195                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
3196                         .update         (vk, device);
3197
3198                 // Color attachment
3199                 m_colorFormat                                           = VK_FORMAT_R8G8B8A8_UNORM;
3200                 m_colorImageSubresourceRange            = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3201                 m_colorImageExtent                                      = makeExtent3D(16u, 16u, 1u);
3202                 m_colorAttachmentImage                          = de::MovePtr<Image>(new Image(vk, device, allocator,
3203                         makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
3204                         MemoryRequirement::Any));
3205
3206                 // Pipeline
3207                 m_colorAttachmentView   = makeImageView         (vk, device, **m_colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorImageSubresourceRange);
3208                 m_renderPass                    = makeRenderPass        (vk, device, m_colorFormat);
3209                 m_framebuffer                   = makeFramebuffer       (vk, device, *m_renderPass, *m_colorAttachmentView, m_colorImageExtent.width, m_colorImageExtent.height, 1u);
3210                 m_pipelineLayout                = makePipelineLayout(vk, device, *m_descriptorSetLayout);
3211
3212                 m_pipeline = GraphicsPipelineBuilder()
3213                         .setPrimitiveTopology                   (VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
3214                         .setRenderSize                                  (tcu::IVec2(static_cast<int>(m_colorImageExtent.width), static_cast<int>(m_colorImageExtent.height)))
3215                         .setVertexInputSingleAttribute  (VK_FORMAT_R32G32B32A32_UINT, tcu::getPixelSize(mapVkFormat(VK_FORMAT_R32G32B32A32_UINT)))
3216                         .setShader                                              (vk, device, VK_SHADER_STAGE_VERTEX_BIT,        context.getBinaryCollection().get("input_vert"), DE_NULL)
3217                         .setShader                                              (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,      context.getBinaryCollection().get("input_frag"), DE_NULL)
3218                         .build                                                  (vk, device, *m_pipelineLayout, *m_renderPass, context.getPipelineCacheData());
3219         }
3220
3221         void recordCommands (const VkCommandBuffer cmdBuffer)
3222         {
3223                 const DeviceInterface&  vk                              = m_context.getDeviceInterface();
3224                 const VkDeviceSize              dataSizeBytes   = m_resource.getBuffer().size;
3225
3226                 // Change color attachment image layout
3227                 {
3228                         const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
3229                                 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
3230                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3231                                 **m_colorAttachmentImage, m_colorImageSubresourceRange);
3232
3233                         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
3234                                 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
3235                 }
3236
3237                 {
3238                         const VkRect2D renderArea = {
3239                                 makeOffset2D(0, 0),
3240                                 makeExtent2D(m_colorImageExtent.width, m_colorImageExtent.height),
3241                         };
3242                         const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3243
3244                         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, clearColor);
3245                 }
3246
3247                 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
3248                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
3249                 {
3250                         const VkDeviceSize vertexBufferOffset = 0ull;
3251                         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_resource.getBuffer().handle, &vertexBufferOffset);
3252                 }
3253
3254                 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(dataSizeBytes / sizeof(tcu::UVec4)), 1u, 0u, 0u);
3255
3256                 const VkBufferMemoryBarrier     barrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_outputBuffer, 0u, m_resource.getBuffer().size);
3257                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
3258
3259                 endRenderPass(vk, cmdBuffer);
3260         }
3261
3262         SyncInfo getSyncInfo (void) const
3263         {
3264                 const SyncInfo syncInfo =
3265                 {
3266                         VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,             // VkPipelineStageFlags         stageMask;
3267                         VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,    // VkAccessFlags                        accessMask;
3268                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        imageLayout;
3269                 };
3270                 return syncInfo;
3271         }
3272
3273         Data getData (void) const
3274         {
3275                 return getHostBufferData(m_context, *m_outputBuffer, m_resource.getBuffer().size);
3276         }
3277
3278 private:
3279         OperationContext&                       m_context;
3280         Resource&                                       m_resource;
3281         de::MovePtr<Buffer>                     m_outputBuffer;
3282         de::MovePtr<Buffer>                     m_indexBuffer;
3283         de::MovePtr<Buffer>                     m_indirectBuffer;
3284         Move<VkRenderPass>                      m_renderPass;
3285         Move<VkFramebuffer>                     m_framebuffer;
3286         Move<VkPipelineLayout>          m_pipelineLayout;
3287         Move<VkPipeline>                        m_pipeline;
3288         VkFormat                                        m_colorFormat;
3289         de::MovePtr<Image>                      m_colorAttachmentImage;
3290         Move<VkImageView>                       m_colorAttachmentView;
3291         VkExtent3D                                      m_colorImageExtent;
3292         VkImageSubresourceRange         m_colorImageSubresourceRange;
3293         Move<VkDescriptorPool>          m_descriptorPool;
3294         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
3295         Move<VkDescriptorSet>           m_descriptorSet;
3296 };
3297
3298 class Support : public OperationSupport
3299 {
3300 public:
3301         Support (const ResourceDescription& resourceDesc)
3302                 : m_resourceDesc        (resourceDesc)
3303         {
3304                 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_BUFFER);
3305         }
3306
3307         void initPrograms (SourceCollections& programCollection) const
3308         {
3309                 // Vertex
3310                 {
3311                         int vertexStride = sizeof(tcu::UVec4);
3312                         std::ostringstream src;
3313                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
3314                                 << "\n"
3315                                 << "layout(location = 0) in uvec4 v_in_data;\n"
3316                                 << "layout(set = 0, binding = 0, std140) writeonly buffer Output {\n"
3317                                 << "    uvec4 data[" << m_resourceDesc.size.x()/vertexStride << "];\n"
3318                                 << "} b_out;\n"
3319                                 << "\n"
3320                                 << "void main (void)\n"
3321                                 << "{\n"
3322                                 << "    b_out.data[gl_VertexIndex] = v_in_data;\n"
3323                                 << "}\n";
3324                         programCollection.glslSources.add("input_vert") << glu::VertexSource(src.str());
3325                 }
3326
3327                 // Fragment
3328                 {
3329                         std::ostringstream src;
3330                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
3331                                 << "\n"
3332                                 << "layout(location = 0) out vec4 o_color;\n"
3333                                 << "\n"
3334                                 << "void main (void)\n"
3335                                 << "{\n"
3336                                 << "    o_color = vec4(1.0);\n"
3337                                 << "}\n";
3338                         programCollection.glslSources.add("input_frag") << glu::FragmentSource(src.str());
3339                 }
3340         }
3341
3342         deUint32 getResourceUsageFlags (void) const
3343         {
3344                 return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
3345         }
3346
3347         VkQueueFlags getQueueFlags (void) const
3348         {
3349                 return VK_QUEUE_GRAPHICS_BIT;
3350         }
3351
3352         de::MovePtr<Operation> build (OperationContext& context, Resource& resource) const
3353         {
3354                 return de::MovePtr<Operation>(new Implementation(context, resource));
3355         }
3356
3357 private:
3358         const ResourceDescription       m_resourceDesc;
3359 };
3360
3361 } // VertexInput
3362
3363 } // anonymous ns
3364
3365 OperationContext::OperationContext (Context& context, PipelineCacheData& pipelineCacheData)
3366         : m_vki                                 (context.getInstanceInterface())
3367         , m_vk                                  (context.getDeviceInterface())
3368         , m_physicalDevice              (context.getPhysicalDevice())
3369         , m_device                              (context.getDevice())
3370         , m_allocator                   (context.getDefaultAllocator())
3371         , m_progCollection              (context.getBinaryCollection())
3372         , m_pipelineCacheData   (pipelineCacheData)
3373 {
3374 }
3375
3376 OperationContext::OperationContext (Context& context, PipelineCacheData& pipelineCacheData, const DeviceInterface& vk, const VkDevice device, vk::Allocator& allocator)
3377         : m_vki                                 (context.getInstanceInterface())
3378         , m_vk                                  (vk)
3379         , m_physicalDevice              (context.getPhysicalDevice())
3380         , m_device                              (device)
3381         , m_allocator                   (allocator)
3382         , m_progCollection              (context.getBinaryCollection())
3383         , m_pipelineCacheData   (pipelineCacheData)
3384 {
3385 }
3386
3387 Resource::Resource (OperationContext& context, const ResourceDescription& desc, const deUint32 usage, const vk::VkSharingMode sharingMode, const std::vector<deUint32>& queueFamilyIndex)
3388         : m_type        (desc.type)
3389 {
3390         const DeviceInterface&          vk                      = context.getDeviceInterface();
3391         const InstanceInterface&        vki                     = context.getInstanceInterface();
3392         const VkDevice                          device          = context.getDevice();
3393         const VkPhysicalDevice          physDevice      = context.getPhysicalDevice();
3394         Allocator&                                      allocator       = context.getAllocator();
3395
3396         if (m_type == RESOURCE_TYPE_BUFFER || isIndirectBuffer(m_type))
3397         {
3398                 m_bufferData.offset                                     = 0u;
3399                 m_bufferData.size                                       = static_cast<VkDeviceSize>(desc.size.x());
3400                 VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData.size, usage);
3401                 bufferCreateInfo.sharingMode            = sharingMode;
3402                 if (queueFamilyIndex.size() > 0)
3403                 {
3404                         bufferCreateInfo.queueFamilyIndexCount  = static_cast<deUint32>(queueFamilyIndex.size());
3405                         bufferCreateInfo.pQueueFamilyIndices    = &queueFamilyIndex[0];
3406                 }
3407                 m_buffer                        = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
3408                 m_bufferData.handle     = **m_buffer;
3409         }
3410         else if (m_type == RESOURCE_TYPE_IMAGE)
3411         {
3412                 m_imageData.extent                              = makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z()));
3413                 m_imageData.imageType                   = desc.imageType;
3414                 m_imageData.format                              = desc.imageFormat;
3415                 m_imageData.subresourceRange    = makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u);
3416                 m_imageData.subresourceLayers   = makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u);
3417                 VkImageCreateInfo imageInfo             = makeImageCreateInfo(m_imageData.imageType, m_imageData.extent, m_imageData.format, usage);
3418                 imageInfo.sharingMode                   = sharingMode;
3419                 if (queueFamilyIndex.size() > 0)
3420                 {
3421                         imageInfo.queueFamilyIndexCount = static_cast<deUint32>(queueFamilyIndex.size());
3422                         imageInfo.pQueueFamilyIndices   = &queueFamilyIndex[0];
3423                 }
3424
3425                 VkImageFormatProperties imageFormatProperties;
3426                 const VkResult formatResult             = vki.getPhysicalDeviceImageFormatProperties(physDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProperties);
3427
3428                 if (formatResult != VK_SUCCESS)
3429                         TCU_THROW(NotSupportedError, "Image format is not supported");
3430
3431                 m_image                                                 = de::MovePtr<Image>(new Image(vk, device, allocator, imageInfo, MemoryRequirement::Any));
3432                 m_imageData.handle                              = **m_image;
3433         }
3434         else
3435                 DE_ASSERT(0);
3436 }
3437
3438 //! \note This function exists for performance reasons. We're creating a lot of tests and checking requirements here
3439 //!       before creating an OperationSupport object is faster.
3440 bool isResourceSupported (const OperationName opName, const ResourceDescription& resourceDesc)
3441 {
3442         switch (opName)
3443         {
3444                 case OPERATION_NAME_WRITE_FILL_BUFFER:
3445                 case OPERATION_NAME_WRITE_COPY_BUFFER:
3446                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:
3447                 case OPERATION_NAME_WRITE_SSBO_VERTEX:
3448                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:
3449                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:
3450                 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:
3451                 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:
3452                 case OPERATION_NAME_WRITE_SSBO_COMPUTE:
3453                 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:
3454                 case OPERATION_NAME_READ_COPY_BUFFER:
3455                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:
3456                 case OPERATION_NAME_READ_SSBO_VERTEX:
3457                 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:
3458                 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:
3459                 case OPERATION_NAME_READ_SSBO_GEOMETRY:
3460                 case OPERATION_NAME_READ_SSBO_FRAGMENT:
3461                 case OPERATION_NAME_READ_SSBO_COMPUTE:
3462                 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:
3463                 case OPERATION_NAME_READ_VERTEX_INPUT:
3464                         return resourceDesc.type == RESOURCE_TYPE_BUFFER;
3465
3466                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:
3467                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:
3468                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW;
3469
3470                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:
3471                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:
3472                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED;
3473
3474                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:
3475                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:
3476                         return resourceDesc.type == RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH;
3477
3478                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:
3479                         return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UPDATE_BUFFER_SIZE;
3480
3481                 case OPERATION_NAME_WRITE_COPY_IMAGE:
3482                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:
3483                 case OPERATION_NAME_READ_COPY_IMAGE:
3484                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:
3485                         return resourceDesc.type == RESOURCE_TYPE_IMAGE;
3486
3487                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:
3488                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType != VK_IMAGE_TYPE_3D;
3489
3490                 case OPERATION_NAME_WRITE_BLIT_IMAGE:
3491                 case OPERATION_NAME_READ_BLIT_IMAGE:
3492                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:
3493                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:
3494                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:
3495                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:
3496                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:
3497                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:
3498                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:
3499                 case OPERATION_NAME_READ_IMAGE_VERTEX:
3500                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:
3501                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:
3502                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:
3503                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:
3504                 case OPERATION_NAME_READ_IMAGE_COMPUTE:
3505                 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:
3506                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT;
3507
3508                 case OPERATION_NAME_READ_UBO_VERTEX:
3509                 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:
3510                 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:
3511                 case OPERATION_NAME_READ_UBO_GEOMETRY:
3512                 case OPERATION_NAME_READ_UBO_FRAGMENT:
3513                 case OPERATION_NAME_READ_UBO_COMPUTE:
3514                 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:
3515                         return resourceDesc.type == RESOURCE_TYPE_BUFFER && resourceDesc.size.x() <= MAX_UBO_RANGE;
3516
3517                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:
3518                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageAspect == VK_IMAGE_ASPECT_COLOR_BIT;
3519
3520                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:
3521                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
3522
3523                 case OPERATION_NAME_WRITE_DRAW:
3524                 case OPERATION_NAME_WRITE_DRAW_INDEXED:
3525                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:
3526                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:
3527                         return resourceDesc.type == RESOURCE_TYPE_IMAGE && resourceDesc.imageType == VK_IMAGE_TYPE_2D
3528                                 && (resourceDesc.imageAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0;
3529
3530                 default:
3531                         DE_ASSERT(0);
3532                         return false;
3533         }
3534 }
3535
3536 std::string getOperationName (const OperationName opName)
3537 {
3538         switch (opName)
3539         {
3540                 case OPERATION_NAME_WRITE_FILL_BUFFER:                                          return "write_fill_buffer";
3541                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:                                        return "write_update_buffer";
3542                 case OPERATION_NAME_WRITE_COPY_BUFFER:                                          return "write_copy_buffer";
3543                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:                         return "write_copy_buffer_to_image";
3544                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:                         return "write_copy_image_to_buffer";
3545                 case OPERATION_NAME_WRITE_COPY_IMAGE:                                           return "write_copy_image";
3546                 case OPERATION_NAME_WRITE_BLIT_IMAGE:                                           return "write_blit_image";
3547                 case OPERATION_NAME_WRITE_SSBO_VERTEX:                                          return "write_ssbo_vertex";
3548                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_CONTROL:            return "write_ssbo_tess_control";
3549                 case OPERATION_NAME_WRITE_SSBO_TESSELLATION_EVALUATION:         return "write_ssbo_tess_eval";
3550                 case OPERATION_NAME_WRITE_SSBO_GEOMETRY:                                        return "write_ssbo_geometry";
3551                 case OPERATION_NAME_WRITE_SSBO_FRAGMENT:                                        return "write_ssbo_fragment";
3552                 case OPERATION_NAME_WRITE_SSBO_COMPUTE:                                         return "write_ssbo_compute";
3553                 case OPERATION_NAME_WRITE_SSBO_COMPUTE_INDIRECT:                        return "write_ssbo_compute_indirect";
3554                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:                                         return "write_image_vertex";
3555                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:           return "write_image_tess_control";
3556                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:        return "write_image_tess_eval";
3557                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:                                       return "write_image_geometry";
3558                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:                                       return "write_image_fragment";
3559                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:                                        return "write_image_compute";
3560                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE_INDIRECT:                       return "write_image_compute_indirect";
3561                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:                            return "write_clear_color_image";
3562                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:            return "write_clear_depth_stencil_image";
3563                 case OPERATION_NAME_WRITE_DRAW:                                                         return "write_draw";
3564                 case OPERATION_NAME_WRITE_DRAW_INDEXED:                                         return "write_draw_indexed";
3565                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:                                        return "write_draw_indirect";
3566                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:                        return "write_draw_indexed_indirect";
3567                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:                            return "write_clear_attachments";
3568                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:                         return "write_indirect_buffer_draw";
3569                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:         return "write_indirect_buffer_draw_indexed";
3570                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:                     return "write_indirect_buffer_dispatch";
3571
3572                 case OPERATION_NAME_READ_COPY_BUFFER:                                           return "read_copy_buffer";
3573                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:                          return "read_copy_buffer_to_image";
3574                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:                          return "read_copy_image_to_buffer";
3575                 case OPERATION_NAME_READ_COPY_IMAGE:                                            return "read_copy_image";
3576                 case OPERATION_NAME_READ_BLIT_IMAGE:                                            return "read_blit_image";
3577                 case OPERATION_NAME_READ_UBO_VERTEX:                                            return "read_ubo_vertex";
3578                 case OPERATION_NAME_READ_UBO_TESSELLATION_CONTROL:                      return "read_ubo_tess_control";
3579                 case OPERATION_NAME_READ_UBO_TESSELLATION_EVALUATION:           return "read_ubo_tess_eval";
3580                 case OPERATION_NAME_READ_UBO_GEOMETRY:                                          return "read_ubo_geometry";
3581                 case OPERATION_NAME_READ_UBO_FRAGMENT:                                          return "read_ubo_fragment";
3582                 case OPERATION_NAME_READ_UBO_COMPUTE:                                           return "read_ubo_compute";
3583                 case OPERATION_NAME_READ_UBO_COMPUTE_INDIRECT:                          return "read_ubo_compute_indirect";
3584                 case OPERATION_NAME_READ_SSBO_VERTEX:                                           return "read_ssbo_vertex";
3585                 case OPERATION_NAME_READ_SSBO_TESSELLATION_CONTROL:                     return "read_ssbo_tess_control";
3586                 case OPERATION_NAME_READ_SSBO_TESSELLATION_EVALUATION:          return "read_ssbo_tess_eval";
3587                 case OPERATION_NAME_READ_SSBO_GEOMETRY:                                         return "read_ssbo_geometry";
3588                 case OPERATION_NAME_READ_SSBO_FRAGMENT:                                         return "read_ssbo_fragment";
3589                 case OPERATION_NAME_READ_SSBO_COMPUTE:                                          return "read_ssbo_compute";
3590                 case OPERATION_NAME_READ_SSBO_COMPUTE_INDIRECT:                         return "read_ssbo_compute_indirect";
3591                 case OPERATION_NAME_READ_IMAGE_VERTEX:                                          return "read_image_vertex";
3592                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:            return "read_image_tess_control";
3593                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:         return "read_image_tess_eval";
3594                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:                                        return "read_image_geometry";
3595                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:                                        return "read_image_fragment";
3596                 case OPERATION_NAME_READ_IMAGE_COMPUTE:                                         return "read_image_compute";
3597                 case OPERATION_NAME_READ_IMAGE_COMPUTE_INDIRECT:                        return "read_image_compute_indirect";
3598                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:                          return "read_indirect_buffer_draw";
3599                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:          return "read_indirect_buffer_draw_indexed";
3600                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:                      return "read_indirect_buffer_dispatch";
3601                 case OPERATION_NAME_READ_VERTEX_INPUT:                                          return "read_vertex_input";
3602
3603                 default:
3604                         DE_ASSERT(0);
3605                         return "";
3606         }
3607 }
3608
3609 de::MovePtr<OperationSupport> makeOperationSupport (const OperationName opName, const ResourceDescription& resourceDesc)
3610 {
3611         switch (opName)
3612         {
3613                 case OPERATION_NAME_WRITE_FILL_BUFFER:                                          return de::MovePtr<OperationSupport>(new FillUpdateBuffer       ::Support               (resourceDesc, FillUpdateBuffer::BUFFER_OP_FILL));
3614                 case OPERATION_NAME_WRITE_UPDATE_BUFFER:                                        return de::MovePtr<OperationSupport>(new FillUpdateBuffer       ::Support               (resourceDesc, FillUpdateBuffer::BUFFER_OP_UPDATE));
3615                 case OPERATION_NAME_WRITE_COPY_BUFFER:                                          return de::MovePtr<OperationSupport>(new CopyBuffer                     ::Support               (resourceDesc, ACCESS_MODE_WRITE));
3616                 case OPERATION_NAME_WRITE_COPY_BUFFER_TO_IMAGE:                         return de::MovePtr<OperationSupport>(new CopyBufferToImage      ::Support               (resourceDesc, ACCESS_MODE_WRITE));
3617                 case OPERATION_NAME_WRITE_COPY_IMAGE_TO_BUFFER:                         return de::MovePtr<OperationSupport>(new CopyImageToBuffer      ::Support               (resourceDesc, ACCESS_MODE_WRITE));
3618                 case OPERATION_NAME_WRITE_COPY_IMAGE:                                           return de::MovePtr<OperationSupport>(new CopyBlitImage          ::Support               (resourceDesc, CopyBlitImage::TYPE_COPY, ACCESS_MODE_WRITE));
3619                 case OPERATION_NAME_WRITE_BLIT_IMAGE:                                           return de::MovePtr<OperationSupport>(new CopyBlitImage          ::Support               (resourceDesc, CopyBlitImage::TYPE_BLIT, ACCESS_MODE_WRITE));
3620                 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));
3621                 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));
3622                 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));
3623                 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));
3624                 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));
3625                 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));
3626                 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));
3627                 case OPERATION_NAME_WRITE_IMAGE_VERTEX:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_VERTEX_BIT));
3628                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_CONTROL:           return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
3629                 case OPERATION_NAME_WRITE_IMAGE_TESSELLATION_EVALUATION:        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
3630                 case OPERATION_NAME_WRITE_IMAGE_GEOMETRY:                                       return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_GEOMETRY_BIT));
3631                 case OPERATION_NAME_WRITE_IMAGE_FRAGMENT:                                       return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_FRAGMENT_BIT));
3632                 case OPERATION_NAME_WRITE_IMAGE_COMPUTE:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_WRITE, VK_SHADER_STAGE_COMPUTE_BIT));
3633                 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));
3634                 case OPERATION_NAME_WRITE_CLEAR_COLOR_IMAGE:                            return de::MovePtr<OperationSupport>(new ClearImage                     ::Support               (resourceDesc, ClearImage::CLEAR_MODE_COLOR));
3635                 case OPERATION_NAME_WRITE_CLEAR_DEPTH_STENCIL_IMAGE:            return de::MovePtr<OperationSupport>(new ClearImage                     ::Support               (resourceDesc, ClearImage::CLEAR_MODE_DEPTH_STENCIL));
3636                 case OPERATION_NAME_WRITE_DRAW:                                                         return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW));
3637                 case OPERATION_NAME_WRITE_DRAW_INDEXED:                                         return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED));
3638                 case OPERATION_NAME_WRITE_DRAW_INDIRECT:                                        return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDIRECT));
3639                 case OPERATION_NAME_WRITE_DRAW_INDEXED_INDIRECT:                        return de::MovePtr<OperationSupport>(new Draw                           ::Support               (resourceDesc, Draw::DRAW_CALL_DRAW_INDEXED_INDIRECT));
3640                 case OPERATION_NAME_WRITE_CLEAR_ATTACHMENTS:                            return de::MovePtr<OperationSupport>(new ClearAttachments       ::Support               (resourceDesc));
3641                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW:                         return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
3642                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DRAW_INDEXED:         return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
3643                 case OPERATION_NAME_WRITE_INDIRECT_BUFFER_DISPATCH:                     return de::MovePtr<OperationSupport>(new IndirectBuffer         ::WriteSupport  (resourceDesc));
3644
3645                 case OPERATION_NAME_READ_COPY_BUFFER:                                           return de::MovePtr<OperationSupport>(new CopyBuffer                     ::Support               (resourceDesc, ACCESS_MODE_READ));
3646                 case OPERATION_NAME_READ_COPY_BUFFER_TO_IMAGE:                          return de::MovePtr<OperationSupport>(new CopyBufferToImage      ::Support               (resourceDesc, ACCESS_MODE_READ));
3647                 case OPERATION_NAME_READ_COPY_IMAGE_TO_BUFFER:                          return de::MovePtr<OperationSupport>(new CopyImageToBuffer      ::Support               (resourceDesc, ACCESS_MODE_READ));
3648                 case OPERATION_NAME_READ_COPY_IMAGE:                                            return de::MovePtr<OperationSupport>(new CopyBlitImage          ::Support               (resourceDesc, CopyBlitImage::TYPE_COPY, ACCESS_MODE_READ));
3649                 case OPERATION_NAME_READ_BLIT_IMAGE:                                            return de::MovePtr<OperationSupport>(new CopyBlitImage          ::Support               (resourceDesc, CopyBlitImage::TYPE_BLIT, ACCESS_MODE_READ));
3650                 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));
3651                 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));
3652                 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));
3653                 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));
3654                 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));
3655                 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));
3656                 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));
3657                 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));
3658                 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));
3659                 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));
3660                 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));
3661                 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));
3662                 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));
3663                 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));
3664                 case OPERATION_NAME_READ_IMAGE_VERTEX:                                          return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_VERTEX_BIT));
3665                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_CONTROL:            return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
3666                 case OPERATION_NAME_READ_IMAGE_TESSELLATION_EVALUATION:         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
3667                 case OPERATION_NAME_READ_IMAGE_GEOMETRY:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_GEOMETRY_BIT));
3668                 case OPERATION_NAME_READ_IMAGE_FRAGMENT:                                        return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_FRAGMENT_BIT));
3669                 case OPERATION_NAME_READ_IMAGE_COMPUTE:                                         return de::MovePtr<OperationSupport>(new ShaderAccess           ::ImageSupport  (resourceDesc, ACCESS_MODE_READ, VK_SHADER_STAGE_COMPUTE_BIT));
3670                 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));
3671                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW:                          return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
3672                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DRAW_INDEXED:          return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
3673                 case OPERATION_NAME_READ_INDIRECT_BUFFER_DISPATCH:                      return de::MovePtr<OperationSupport>(new IndirectBuffer         ::ReadSupport   (resourceDesc));
3674                 case OPERATION_NAME_READ_VERTEX_INPUT:                                          return de::MovePtr<OperationSupport>(new VertexInput            ::Support               (resourceDesc));
3675
3676                 default:
3677                         DE_ASSERT(0);
3678                         return de::MovePtr<OperationSupport>();
3679         }
3680 }
3681
3682 } // synchronization
3683 } // vkt