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