Expand tests for mutable images
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageMutableTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 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 Tests for mutable images
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktImageMutableTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktImageTexture.hpp"
27
28 #include "vkBuilderUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkImageUtil.hpp"
31
32 #include "deUniquePtr.hpp"
33 #include "deSharedPtr.hpp"
34
35 #include "tcuImageCompare.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuTextureUtil.hpp"
38
39 #include <string>
40 #include <vector>
41
42 using namespace vk;
43 using namespace tcu;
44
45 using de::UniquePtr;
46 using de::MovePtr;
47 using de::SharedPtr;
48 using std::vector;
49
50 namespace vkt
51 {
52 namespace image
53 {
54
55 typedef SharedPtr<Unique<VkPipeline> >  SharedPtrVkPipeline;
56 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
57
58 template<typename T>
59 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
60 {
61         return SharedPtr<Unique<T> >(new Unique<T>(move));
62 }
63
64 enum Upload {
65         UPLOAD_CLEAR = 0,
66         UPLOAD_COPY,
67         UPLOAD_STORE,
68         UPLOAD_DRAW,
69         UPLOAD_LAST
70 };
71
72 enum Download {
73         DOWNLOAD_COPY = 0,
74         DOWNLOAD_LOAD,
75         DOWNLOAD_TEXTURE,
76         DOWNLOAD_LAST
77 };
78
79 std::string getUploadString (const int upload)
80 {
81         const char* strs[] = { "clear", "copy", "store", "draw" };
82         return strs[upload];
83 }
84
85 std::string getDownloadString (const int download)
86 {
87         const char* strs[] = { "copy", "load", "texture" };
88         return strs[download];
89 }
90
91 struct CaseDef
92 {
93         ImageType               imageType;
94         IVec3                   size;
95         deUint32                numLayers;
96         VkFormat                imageFormat;
97         VkFormat                viewFormat;
98         enum Upload             upload;
99         enum Download   download;
100 };
101
102 static const deUint32 COLOR_TABLE_SIZE = 4;
103
104 // Reference color values for float color rendering. Values have been chosen
105 // so that when the bit patterns are reinterpreted as a 16-bit float, we do not
106 // run into NaN / inf / denorm values.
107 static const Vec4       COLOR_TABLE_FLOAT[COLOR_TABLE_SIZE]     =
108 {
109         Vec4(0.00f, 0.40f, 0.80f, 0.10f),
110         Vec4(0.10f, 0.50f, 0.90f, 0.20f),
111         Vec4(0.20f, 0.60f, 1.00f, 0.30f),
112         Vec4(0.30f, 0.70f, 0.00f, 0.40f),
113 };
114
115 // Reference color values for integer color rendering. We avoid negative
116 // values (even for SINT formats) to avoid the situation where sign extension
117 // leads to NaN / inf values when they are reinterpreted with a float
118 // format.
119 static const IVec4      COLOR_TABLE_INT[COLOR_TABLE_SIZE]       =
120 {
121         IVec4(112,  60, 101,  41),
122         IVec4( 60, 101,  41, 112),
123         IVec4( 41, 112,  60, 101),
124         IVec4(101,  41, 112,  60),
125 };
126
127 // Reference clear colors created from the color table values
128 static const VkClearValue REFERENCE_CLEAR_COLOR_FLOAT[COLOR_TABLE_SIZE] =
129 {
130         makeClearValueColorF32(COLOR_TABLE_FLOAT[0].x(), COLOR_TABLE_FLOAT[0].y(), COLOR_TABLE_FLOAT[0].z(), COLOR_TABLE_FLOAT[0].w()),
131         makeClearValueColorF32(COLOR_TABLE_FLOAT[1].x(), COLOR_TABLE_FLOAT[1].y(), COLOR_TABLE_FLOAT[1].z(), COLOR_TABLE_FLOAT[1].w()),
132         makeClearValueColorF32(COLOR_TABLE_FLOAT[2].x(), COLOR_TABLE_FLOAT[2].y(), COLOR_TABLE_FLOAT[2].z(), COLOR_TABLE_FLOAT[2].w()),
133         makeClearValueColorF32(COLOR_TABLE_FLOAT[3].x(), COLOR_TABLE_FLOAT[3].y(), COLOR_TABLE_FLOAT[3].z(), COLOR_TABLE_FLOAT[3].w()),
134 };
135
136 static const VkClearValue REFERENCE_CLEAR_COLOR_INT[COLOR_TABLE_SIZE]   =
137 {
138         makeClearValueColorI32(COLOR_TABLE_INT[0].x(), COLOR_TABLE_INT[0].y(), COLOR_TABLE_INT[0].z(), COLOR_TABLE_INT[0].w()),
139         makeClearValueColorI32(COLOR_TABLE_INT[1].x(), COLOR_TABLE_INT[1].y(), COLOR_TABLE_INT[1].z(), COLOR_TABLE_INT[1].w()),
140         makeClearValueColorI32(COLOR_TABLE_INT[2].x(), COLOR_TABLE_INT[2].y(), COLOR_TABLE_INT[2].z(), COLOR_TABLE_INT[2].w()),
141         makeClearValueColorI32(COLOR_TABLE_INT[3].x(), COLOR_TABLE_INT[3].y(), COLOR_TABLE_INT[3].z(), COLOR_TABLE_INT[3].w()),
142 };
143
144 static const Texture s_textures[] =
145 {
146         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(32, 32, 1),  1),
147         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(32, 32, 1),  4),
148 };
149
150 VkImageType getImageType (const ImageType textureImageType)
151 {
152         switch (textureImageType)
153         {
154                 case IMAGE_TYPE_2D:
155                 case IMAGE_TYPE_2D_ARRAY:
156                         return VK_IMAGE_TYPE_2D;
157
158                 default:
159                         DE_ASSERT(0);
160                         return VK_IMAGE_TYPE_LAST;
161         }
162 }
163
164 VkImageViewType getImageViewType (const ImageType textureImageType)
165 {
166         switch (textureImageType)
167         {
168                 case IMAGE_TYPE_2D:
169                         return VK_IMAGE_VIEW_TYPE_2D;
170                 case IMAGE_TYPE_2D_ARRAY:
171                         return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
172
173                 default:
174                         DE_ASSERT(0);
175                         return VK_IMAGE_VIEW_TYPE_LAST;
176         }
177 }
178
179 static const VkFormat s_formats[] =
180 {
181         VK_FORMAT_R32G32B32A32_SFLOAT,
182         VK_FORMAT_R16G16B16A16_SFLOAT,
183         VK_FORMAT_R32G32_SFLOAT,
184         VK_FORMAT_R16G16_SFLOAT,
185         VK_FORMAT_R32_SFLOAT,
186
187         VK_FORMAT_R32G32B32A32_UINT,
188         VK_FORMAT_R16G16B16A16_UINT,
189         VK_FORMAT_R8G8B8A8_UINT,
190         VK_FORMAT_R32G32_UINT,
191         VK_FORMAT_R16G16_UINT,
192         VK_FORMAT_R32_UINT,
193
194         VK_FORMAT_R32G32B32A32_SINT,
195         VK_FORMAT_R16G16B16A16_SINT,
196         VK_FORMAT_R8G8B8A8_SINT,
197         VK_FORMAT_R32G32_SINT,
198         VK_FORMAT_R16G16_SINT,
199         VK_FORMAT_R32_SINT,
200
201         VK_FORMAT_R8G8B8A8_UNORM,
202
203         VK_FORMAT_R8G8B8A8_SNORM,
204 };
205
206 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
207 {
208         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
209 }
210
211 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
212 {
213         std::ostringstream str;
214         if (numComponents == 1)
215                 str << (isUint ? "uint" : isSint ? "int" : "float");
216         else
217                 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
218
219         return str.str();
220 }
221
222 std::string getShaderSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
223 {
224         std::ostringstream samplerType;
225
226         if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
227                 samplerType << "u";
228         else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
229                 samplerType << "i";
230
231         switch (type)
232         {
233                 case VK_IMAGE_VIEW_TYPE_2D:
234                         samplerType << "sampler2D";
235                         break;
236
237                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
238                         samplerType << "sampler2DArray";
239                         break;
240
241                 default:
242                         DE_FATAL("Ivalid image view type");
243                         break;
244         }
245
246         return samplerType.str();
247 }
248
249 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
250 {
251         if (caseDef.upload == UPLOAD_DRAW)
252         {
253                 {
254                         std::ostringstream src;
255                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
256                                 << "\n"
257                                 << "layout(location = 0) in  vec4 in_position;\n"
258                                 << "layout(location = 1) in  vec4 in_color;\n"
259                                 << "layout(location = 0) out vec4 out_color;\n"
260                                 << "\n"
261                                 << "out gl_PerVertex {\n"
262                                 << "    vec4 gl_Position;\n"
263                                 << "};\n"
264                                 << "\n"
265                                 << "void main(void)\n"
266                                 << "{\n"
267                                 << "    gl_Position     = in_position;\n"
268                                 << "    out_color       = in_color;\n"
269                                 << "}\n";
270
271                         programCollection.glslSources.add("uploadDrawVert") << glu::VertexSource(src.str());
272                 }
273
274                 {
275                         const int       numComponents           = getNumUsedChannels(mapVkFormat(caseDef.viewFormat).order);
276                         const bool      isUint                          = isUintFormat(caseDef.viewFormat);
277                         const bool      isSint                          = isIntFormat(caseDef.viewFormat);
278                         const std::string colorFormat   = getColorFormatStr(numComponents, isUint, isSint);
279
280                         std::ostringstream src;
281                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
282                                 << "\n"
283                                 << "layout(location = 0) in  vec4 in_color;\n"
284                                 << "layout(location = 0) out " << colorFormat << " out_color;\n"
285                                 << "\n"
286                                 << "void main(void)\n"
287                                 << "{\n"
288                                 << "    out_color = " << colorFormat << "("
289                                 << (numComponents == 1 ? "in_color.r"   :
290                                         numComponents == 2 ? "in_color.rg"  :
291                                         numComponents == 3 ? "in_color.rgb" : "in_color")
292                                 << ");\n"
293                                 << "}\n";
294
295                         programCollection.glslSources.add("uploadDrawFrag") << glu::FragmentSource(src.str());
296                 }
297         }
298
299         if (caseDef.upload == UPLOAD_STORE)
300         {
301                 const TextureFormat     tcuFormat               = mapVkFormat(caseDef.viewFormat);
302                 const std::string       imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
303                 const std::string       imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
304                 const std::string       colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
305                 const bool                      isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
306
307                 std::ostringstream src;
308                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
309                         << "\n"
310                         << "layout (local_size_x = 1) in;\n"
311                         << "\n"
312                         << "layout(binding=0, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"
313                         << "\n"
314                         << "const " << colorTypeStr << " colorTable[] = " << colorTypeStr << "[](\n";
315                 for (deUint32 idx = 0; idx < COLOR_TABLE_SIZE; idx++)
316                 {
317                         if (isIntegerFormat)
318                                 src << "     " << colorTypeStr << "(" << COLOR_TABLE_INT[idx].x() << ", " << COLOR_TABLE_INT[idx].y() << ", " << COLOR_TABLE_INT[idx].z() << ", " << COLOR_TABLE_INT[idx].w() << ")";
319                         else
320                                 src << "     " << colorTypeStr << "(" << COLOR_TABLE_FLOAT[idx].x() << ", " << COLOR_TABLE_FLOAT[idx].y() << ", " << COLOR_TABLE_FLOAT[idx].z() << ", " << COLOR_TABLE_FLOAT[idx].w() << ")";
321                         if (idx < COLOR_TABLE_SIZE - 1)
322                                 src << ",";
323                         src << "\n";
324                 }
325                 src << ");\n"
326                         << "\n"
327                         << "void main(void)\n"
328                         << "{\n";
329                 if (caseDef.imageType == IMAGE_TYPE_2D)
330                 {
331                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
332                 }
333                 else
334                 {
335                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
336                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
337                 }
338                 src << "    " << colorTypeStr << " color = colorTable[gl_GlobalInvocationID.z];\n"
339                         << "    imageStore(u_image, pos, color);\n"
340                         << "}\n";
341
342                 programCollection.glslSources.add("uploadStoreComp") << glu::ComputeSource(src.str());
343         }
344
345         if (caseDef.download == DOWNLOAD_LOAD)
346         {
347                 const TextureFormat     tcuFormat               = mapVkFormat(caseDef.viewFormat);
348                 const std::string       imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
349                 const std::string       imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
350                 const std::string       colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
351
352                 std::ostringstream src;
353                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
354                         << "\n"
355                         << "layout (local_size_x = 1) in;\n"
356                         << "\n"
357                         << "layout(binding=0, " << imageFormatStr << ") readonly uniform " << imageTypeStr << " in_image;\n"
358                         << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
359                         << "\n"
360                         << "void main(void)\n"
361                         << "{\n";
362                 if (caseDef.imageType == IMAGE_TYPE_2D)
363                 {
364                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
365                 }
366                 else
367                 {
368                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
369                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
370                 }
371                 src     << "    imageStore(out_image, pos, imageLoad(in_image, pos));\n"
372                         << "}\n";
373
374                 programCollection.glslSources.add("downloadLoadComp") << glu::ComputeSource(src.str());
375         }
376
377         if (caseDef.download == DOWNLOAD_TEXTURE)
378         {
379                 const TextureFormat             tcuFormat               = mapVkFormat(caseDef.viewFormat);
380                 const VkImageViewType   viewType                = getImageViewType(caseDef.imageType);
381                 const std::string               samplerTypeStr  = getShaderSamplerType(tcuFormat, viewType);
382                 const std::string               imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
383                 const std::string               imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
384                 const std::string               colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
385
386                 std::ostringstream src;
387                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
388                         << "\n"
389                         << "layout (local_size_x = 1) in;\n"
390                         << "\n"
391                         << "layout(binding=0) uniform " << samplerTypeStr << " u_tex;\n"
392                         << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
393                         << "\n"
394                         << "void main(void)\n"
395                         << "{\n";
396                 if (caseDef.imageType == IMAGE_TYPE_2D)
397                 {
398                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
399                 }
400                 else
401                 {
402                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
403                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
404                 }
405                 src     << "    imageStore(out_image, pos, texelFetch(u_tex, pos, 0));\n"
406                         << "}\n";
407
408                 programCollection.glslSources.add("downloadTextureComp") << glu::ComputeSource(src.str());
409         }
410 }
411
412 Move<VkImage> makeImage (const DeviceInterface&         vk,
413                                                  const VkDevice                         device,
414                                                  VkImageCreateFlags                     flags,
415                                                  VkImageType                            imageType,
416                                                  const VkFormat                         format,
417                                                  const IVec3&                           size,
418                                                  const deUint32                         numMipLevels,
419                                                  const deUint32                         numLayers,
420                                                  const VkImageUsageFlags        usage)
421 {
422         const VkImageCreateInfo imageParams =
423         {
424                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
425                 DE_NULL,                                                                        // const void*                          pNext;
426                 flags,                                                                          // VkImageCreateFlags           flags;
427                 imageType,                                                                      // VkImageType                          imageType;
428                 format,                                                                         // VkFormat                                     format;
429                 makeExtent3D(size),                                                     // VkExtent3D                           extent;
430                 numMipLevels,                                                           // deUint32                                     mipLevels;
431                 numLayers,                                                                      // deUint32                                     arrayLayers;
432                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
433                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
434                 usage,                                                                          // VkImageUsageFlags            usage;
435                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
436                 0u,                                                                                     // deUint32                                     queueFamilyIndexCount;
437                 DE_NULL,                                                                        // const deUint32*                      pQueueFamilyIndices;
438                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        initialLayout;
439         };
440         return createImage(vk, device, &imageParams);
441 }
442
443 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
444 {
445         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
446         return createBuffer(vk, device, &bufferCreateInfo);
447 }
448
449 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
450 {
451         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
452 }
453
454 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
455 {
456         const VkSamplerCreateInfo samplerParams =
457         {
458                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
459                 DE_NULL,                                                                        // const void*                          pNext;
460                 (VkSamplerCreateFlags)0,                                        // VkSamplerCreateFlags         flags;
461                 VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter;
462                 VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
463                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
464                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
465                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
466                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
467                 0.0f,                                                                           // float                                        mipLodBias;
468                 VK_FALSE,                                                                       // VkBool32                                     anisotropyEnable;
469                 1.0f,                                                                           // float                                        maxAnisotropy;
470                 VK_FALSE,                                                                       // VkBool32                                     compareEnable;
471                 VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp                          compareOp;
472                 0.0f,                                                                           // float                                        minLod;
473                 0.0f,                                                                           // float                                        maxLod;
474                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // VkBorderColor                        borderColor;
475                 VK_FALSE,                                                                       // VkBool32                                     unnormalizedCoordinates;
476         };
477
478         return createSampler(vk, device, &samplerParams);
479 }
480
481
482 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&       vk,
483                                                                                    const VkDevice                       device)
484 {
485         const VkPipelineLayoutCreateInfo info =
486         {
487                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
488                 DE_NULL,
489                 (VkPipelineLayoutCreateFlags)0,
490                 0u,
491                 DE_NULL,
492                 0u,
493                 DE_NULL,
494         };
495         return createPipelineLayout(vk, device, &info);
496 }
497
498 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
499                                                                            const VkDevice                               device,
500                                                                            const VkPipelineLayout               pipelineLayout,
501                                                                            const VkRenderPass                   renderPass,
502                                                                            const VkShaderModule                 vertexModule,
503                                                                            const VkShaderModule                 fragmentModule,
504                                                                            const IVec2&                                 renderSize,
505                                                                            const VkPrimitiveTopology    topology,
506                                                                            const deUint32                               subpass)
507 {
508         const VkVertexInputBindingDescription vertexInputBindingDescription =
509         {
510                 0u,                                                                     // uint32_t                             binding;
511                 (uint32_t)(2 * sizeof(Vec4)),           // uint32_t                             stride;
512                 VK_VERTEX_INPUT_RATE_VERTEX,            // VkVertexInputRate    inputRate;
513         };
514
515         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
516         {
517                 {
518                         0u,                                                             // uint32_t                     location;
519                         0u,                                                             // uint32_t                     binding;
520                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
521                         0u,                                                             // uint32_t                     offset;
522                 },
523                 {
524                         1u,                                                             // uint32_t                     location;
525                         0u,                                                             // uint32_t                     binding;
526                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
527                         (uint32_t)sizeof(Vec4),                 // uint32_t                     offset;
528                 }
529         };
530
531         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
532         {
533                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
534                 DE_NULL,                                                                                                        // const void*                                                          pNext;
535                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags        flags;
536                 1u,                                                                                                                     // uint32_t                                                                     vertexBindingDescriptionCount;
537                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
538                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),           // uint32_t                                                                     vertexAttributeDescriptionCount;
539                 vertexInputAttributeDescriptions,                                                       // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
540         };
541
542         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
543         {
544                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
545                 DE_NULL,                                                                                                                // const void*                                                          pNext;
546                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
547                 topology,                                                                                                               // VkPrimitiveTopology                                          topology;
548                 VK_FALSE,                                                                                                               // VkBool32                                                                     primitiveRestartEnable;
549         };
550
551         const VkViewport viewport = makeViewport(
552                 0.0f, 0.0f,
553                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
554                 0.0f, 1.0f);
555
556         const VkRect2D scissor =
557         {
558                 makeOffset2D(0, 0),
559                 makeExtent2D(renderSize.x(), renderSize.y()),
560         };
561
562         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
563         {
564                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          // VkStructureType                                              sType;
565                 DE_NULL,                                                                                                        // const void*                                                  pNext;
566                 (VkPipelineViewportStateCreateFlags)0,                                          // VkPipelineViewportStateCreateFlags   flags;
567                 1u,                                                                                                                     // uint32_t                                                             viewportCount;
568                 &viewport,                                                                                                      // const VkViewport*                                    pViewports;
569                 1u,                                                                                                                     // uint32_t                                                             scissorCount;
570                 &scissor,                                                                                                       // const VkRect2D*                                              pScissors;
571         };
572
573         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
574         {
575                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
576                 DE_NULL,                                                                                                        // const void*                                                          pNext;
577                 (VkPipelineRasterizationStateCreateFlags)0,                                     // VkPipelineRasterizationStateCreateFlags      flags;
578                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable;
579                 VK_FALSE,                                                                                                       // VkBool32                                                                     rasterizerDiscardEnable;
580                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
581                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
582                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
583                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
584                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
585                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
586                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
587                 1.0f,                                                                                                           // float                                                                        lineWidth;
588         };
589
590         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
591         {
592                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
593                 DE_NULL,                                                                                                        // const void*                                                          pNext;
594                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
595                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
596                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
597                 0.0f,                                                                                                           // float                                                                        minSampleShading;
598                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
599                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
600                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
601         };
602
603         const VkStencilOpState stencilOpState = makeStencilOpState(
604                 VK_STENCIL_OP_KEEP,                                                                                     // stencil fail
605                 VK_STENCIL_OP_ZERO,                                                                                     // depth & stencil pass
606                 VK_STENCIL_OP_KEEP,                                                                                     // depth only fail
607                 VK_COMPARE_OP_EQUAL,                                                                            // compare op
608                 ~0u,                                                                                                            // compare mask
609                 ~0u,                                                                                                            // write mask
610                 0u);                                                                                                            // reference
611
612         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
613         {
614                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
615                 DE_NULL,                                                                                                        // const void*                                                          pNext;
616                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
617                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
618                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
619                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
620                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
621                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
622                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
623                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
624                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
625                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
626         };
627
628         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
629         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
630         {
631                 VK_FALSE,                                                                                                       // VkBool32                                     blendEnable;
632                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlendFactor                        srcColorBlendFactor;
633                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlendFactor                        dstColorBlendFactor;
634                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            colorBlendOp;
635                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlendFactor                        srcAlphaBlendFactor;
636                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlendFactor                        dstAlphaBlendFactor;
637                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            alphaBlendOp;
638                 colorComponentsAll,                                                                                     // VkColorComponentFlags        colorWriteMask;
639         };
640
641         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
642         {
643                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
644                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
645                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
646                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
647                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
648                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
649                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
650                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
651         };
652
653         const VkPipelineShaderStageCreateInfo pShaderStages[] =
654         {
655                 {
656                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
657                         DE_NULL,                                                                                                // const void*                                                  pNext;
658                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
659                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
660                         vertexModule,                                                                                   // VkShaderModule                                               module;
661                         "main",                                                                                                 // const char*                                                  pName;
662                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
663                 },
664                 {
665                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
666                         DE_NULL,                                                                                                // const void*                                                  pNext;
667                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
668                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
669                         fragmentModule,                                                                                 // VkShaderModule                                               module;
670                         "main",                                                                                                 // const char*                                                  pName;
671                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
672                 }
673         };
674
675         const VkGraphicsPipelineCreateInfo      graphicsPipelineInfo =
676         {
677                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
678                 DE_NULL,                                                                                        // const void*                                                                          pNext;
679                 0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
680                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
681                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
682                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
683                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
684                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
685                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
686                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
687                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
688                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
689                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
690                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
691                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
692                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
693                 subpass,                                                                                        // deUint32                                                                                     subpass;
694                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
695                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
696         };
697
698         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
699 }
700
701 Move<VkPipeline> makeComputePipeline (const DeviceInterface&            vk,
702                                                                           const VkDevice                                device,
703                                                                           const VkPipelineLayout                pipelineLayout,
704                                                                           const VkShaderModule                  shaderModule,
705                                                                           const VkSpecializationInfo*   specInfo)
706 {
707         const VkPipelineShaderStageCreateInfo shaderStageInfo =
708         {
709                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
710                 DE_NULL,                                                                                                // const void*                                          pNext;
711                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags     flags;
712                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                        stage;
713                 shaderModule,                                                                                   // VkShaderModule                                       module;
714                 "main",                                                                                                 // const char*                                          pName;
715                 specInfo,                                                                                               // const VkSpecializationInfo*          pSpecializationInfo;
716         };
717         const VkComputePipelineCreateInfo pipelineInfo =
718         {
719                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // VkStructureType                                      sType;
720                 DE_NULL,                                                                                                // const void*                                          pNext;
721                 (VkPipelineCreateFlags)0,                                                               // VkPipelineCreateFlags                        flags;
722                 shaderStageInfo,                                                                                // VkPipelineShaderStageCreateInfo      stage;
723                 pipelineLayout,                                                                                 // VkPipelineLayout                                     layout;
724                 DE_NULL,                                                                                                // VkPipeline                                           basePipelineHandle;
725                 0,                                                                                                              // deInt32                                                      basePipelineIndex;
726         };
727         return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
728 }
729
730 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
731                                                                    const VkDevice                       device,
732                                                                    const VkFormat                       colorFormat,
733                                                                    const deUint32                       numLayers)
734 {
735         const VkAttachmentDescription colorAttachmentDescription =
736         {
737                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
738                 colorFormat,                                                                            // VkFormat                                                     format;
739                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
740                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
741                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
742                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
743                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
744                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
745                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
746         };
747         vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
748
749         // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
750         vector<VkAttachmentReference>   colorAttachmentReferences       (numLayers);
751         vector<VkSubpassDescription>    subpasses;
752
753         // Ordering here must match the framebuffer attachments
754         for (deUint32 i = 0; i < numLayers; ++i)
755         {
756                 const VkAttachmentReference attachmentRef =
757                 {
758                         i,                                                                                                      // deUint32                     attachment;
759                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
760                 };
761
762                 colorAttachmentReferences[i]    = attachmentRef;
763
764                 const VkSubpassDescription              subpassDescription      =
765                 {
766                         (VkSubpassDescriptionFlags)0,                                   // VkSubpassDescriptionFlags            flags;
767                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // VkPipelineBindPoint                          pipelineBindPoint;
768                         0u,                                                                                             // deUint32                                                     inputAttachmentCount;
769                         DE_NULL,                                                                                // const VkAttachmentReference*         pInputAttachments;
770                         1u,                                                                                             // deUint32                                                     colorAttachmentCount;
771                         &colorAttachmentReferences[i],                                  // const VkAttachmentReference*         pColorAttachments;
772                         DE_NULL,                                                                                // const VkAttachmentReference*         pResolveAttachments;
773                         DE_NULL,                                                                                // const VkAttachmentReference*         pDepthStencilAttachment;
774                         0u,                                                                                             // deUint32                                                     preserveAttachmentCount;
775                         DE_NULL                                                                                 // const deUint32*                                      pPreserveAttachments;
776                 };
777                 subpasses.push_back(subpassDescription);
778         }
779
780         const VkRenderPassCreateInfo renderPassInfo =
781         {
782                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
783                 DE_NULL,                                                                                                // const void*                                          pNext;
784                 (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
785                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
786                 &attachmentDescriptions[0],                                                             // const VkAttachmentDescription*       pAttachments;
787                 static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
788                 &subpasses[0],                                                                                  // const VkSubpassDescription*          pSubpasses;
789                 0u,                                                                                                             // deUint32                                                     dependencyCount;
790                 DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
791         };
792
793         return createRenderPass(vk, device, &renderPassInfo);
794 }
795
796 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&     vk,
797                                                                          const VkDevice                 device,
798                                                                          const VkRenderPass             renderPass,
799                                                                          const deUint32                 attachmentCount,
800                                                                          const VkImageView*             pAttachments,
801                                                                          const IVec2                    size)
802 {
803         const VkFramebufferCreateInfo framebufferInfo =
804         {
805                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
806                 DE_NULL,
807                 (VkFramebufferCreateFlags)0,
808                 renderPass,
809                 attachmentCount,
810                 pAttachments,
811                 static_cast<deUint32>(size.x()),
812                 static_cast<deUint32>(size.y()),
813                 1u,
814         };
815
816         return createFramebuffer(vk, device, &framebufferInfo);
817 }
818
819 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
820 {
821         return allocateCommandBuffer(vk, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
822 }
823
824 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
825 {
826         MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
827         VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
828         return alloc;
829 }
830
831 MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
832 {
833         MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
834         VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
835         return alloc;
836 }
837
838 vector<Vec4> genVertexData (const CaseDef& caseDef)
839 {
840         vector<Vec4>    vectorData;
841         const bool              isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
842
843         for (deUint32 z = 0; z < caseDef.numLayers; z++)
844         {
845                 const deUint32  colorIdx        = z % COLOR_TABLE_SIZE;
846                 const Vec4              color           = isIntegerFormat ? COLOR_TABLE_INT[colorIdx].cast<float>() : COLOR_TABLE_FLOAT[colorIdx];
847
848                 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
849                 vectorData.push_back(color);
850                 vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
851                 vectorData.push_back(color);
852                 vectorData.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
853                 vectorData.push_back(color);
854                 vectorData.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
855                 vectorData.push_back(color);
856         }
857
858         return vectorData;
859 }
860
861 void generateExpectedImage(const tcu::PixelBufferAccess& image, const CaseDef& caseDef)
862 {
863         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(image.getFormat().type);
864         const bool                                              isIntegerFormat = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
865         const IVec2                                             size                    = caseDef.size.swizzle(0, 1);
866
867         for (int z = 0; z < static_cast<int>(caseDef.numLayers); z++)
868         {
869                 const deUint32  colorIdx        = z % COLOR_TABLE_SIZE;
870                 for (int y = 0; y < size.y(); y++)
871                 for (int x = 0; x < size.x(); x++)
872                 {
873                         if (isIntegerFormat)
874                                 image.setPixel(COLOR_TABLE_INT[colorIdx], x, y, z);
875                         else
876                                 image.setPixel(COLOR_TABLE_FLOAT[colorIdx], x, y, z);
877                 }
878         }
879 }
880
881 VkImageUsageFlags getImageUsageForTestCase (const CaseDef& caseDef)
882 {
883         VkImageUsageFlags flags = 0u;
884
885         switch (caseDef.upload)
886         {
887         case UPLOAD_CLEAR:
888                 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
889                 break;
890         case UPLOAD_DRAW:
891                 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
892                 break;
893         case UPLOAD_STORE:
894                 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
895                 break;
896         case UPLOAD_COPY:
897                 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
898                 break;
899         default:
900                 DE_ASSERT("Invalid upload method");
901                 break;
902         }
903
904         switch (caseDef.download)
905         {
906         case DOWNLOAD_TEXTURE:
907                 flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
908                 break;
909         case DOWNLOAD_LOAD:
910                 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
911                 break;
912         case DOWNLOAD_COPY:
913                 flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
914                 break;
915         default:
916                 DE_ASSERT("Invalid download method");
917                 break;
918         }
919
920         // We can only create a view for the image if it is going to be used for any of these usages,
921         // so let's make sure that we have at least one of them.
922         VkImageUsageFlags viewRequiredFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
923         if (!(flags & viewRequiredFlags))
924                 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
925
926         return flags;
927 }
928
929 // Executes a combination of upload/download methods
930 class UploadDownloadExecutor
931 {
932 public:
933         UploadDownloadExecutor(Context &context, const CaseDef& caseSpec) :
934         m_caseDef(caseSpec),
935         m_haveMaintenance2(de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance2")),
936         m_vk(context.getDeviceInterface()),
937         m_device(context.getDevice()),
938         m_queue(context.getUniversalQueue()),
939         m_queueFamilyIndex(context.getUniversalQueueFamilyIndex()),
940         m_allocator(context.getDefaultAllocator())
941         {
942         }
943
944         void run(Context& context, VkBuffer buffer);
945
946 private:
947         void uploadClear(Context& context);
948         void uploadStore(Context& context);
949         void uploadCopy(Context& context);
950         void uploadDraw(Context& context);
951         void downloadCopy(Context& context, VkBuffer buffer);
952         void downloadTexture(Context& context, VkBuffer buffer);
953         void downloadLoad(Context& context, VkBuffer buffer);
954
955         void copyImageToBuffer(VkImage                          image,
956                                                    VkBuffer                             buffer,
957                                                    const IVec3                  size,
958                                                    const VkAccessFlags  srcAccessMask,
959                                                    const VkImageLayout  oldLayout,
960                                                    const deUint32               numLayers);
961
962         const CaseDef&                                          m_caseDef;
963
964         bool                                                            m_haveMaintenance2;
965
966         const DeviceInterface&                          m_vk;
967         const VkDevice                                          m_device;
968         const VkQueue                                           m_queue;
969         const deUint32                                          m_queueFamilyIndex;
970         Allocator&                                                      m_allocator;
971
972         Move<VkCommandPool>                                     m_cmdPool;
973         Move<VkCommandBuffer>                           m_cmdBuffer;
974
975         bool                                                            m_imageIsIntegerFormat;
976         bool                                                            m_viewIsIntegerFormat;
977
978         // Target image for upload paths
979         Move<VkImage>                                           m_image;
980         MovePtr<Allocation>                                     m_imageAlloc;
981
982         // Upload copy
983         struct
984         {
985                 Move<VkBuffer>                                  colorBuffer;
986                 VkDeviceSize                                    colorBufferSize;
987                 MovePtr<Allocation>                             colorBufferAlloc;
988         } m_uCopy;
989
990         // Upload draw
991         struct
992         {
993                 Move<VkBuffer>                                  vertexBuffer;
994                 MovePtr<Allocation>                             vertexBufferAlloc;
995                 Move<VkPipelineLayout>                  pipelineLayout;
996                 Move<VkRenderPass>                              renderPass;
997                 Move<VkShaderModule>                    vertexModule;
998                 Move<VkShaderModule>                    fragmentModule;
999                 vector<SharedPtrVkImageView>    attachments;
1000                 vector<VkImageView>                             attachmentHandles;
1001                 vector<SharedPtrVkPipeline>             pipelines;
1002                 Move<VkFramebuffer>                             framebuffer;
1003         } m_uDraw;
1004
1005         // Upload store
1006         struct
1007         {
1008                 Move<VkDescriptorPool>                  descriptorPool;
1009                 Move<VkPipelineLayout>                  pipelineLayout;
1010                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1011                 Move<VkDescriptorSet>                   descriptorSet;
1012                 VkDescriptorImageInfo                   imageDescriptorInfo;
1013                 Move<VkShaderModule>                    computeModule;
1014                 Move<VkPipeline>                                computePipeline;
1015                 Move<VkImageView>                               imageView;
1016         } m_uStore;
1017
1018         // Download load
1019         struct
1020         {
1021                 Move<VkDescriptorPool>                  descriptorPool;
1022                 Move<VkPipelineLayout>                  pipelineLayout;
1023                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1024                 Move<VkDescriptorSet>                   descriptorSet;
1025                 Move<VkShaderModule>                    computeModule;
1026                 Move<VkPipeline>                                computePipeline;
1027                 Move<VkImageView>                               inImageView;
1028                 VkDescriptorImageInfo                   inImageDescriptorInfo;
1029                 Move<VkImage>                                   outImage;
1030                 Move<VkImageView>                               outImageView;
1031                 MovePtr<Allocation>                             outImageAlloc;
1032                 VkDescriptorImageInfo                   outImageDescriptorInfo;
1033         } m_dLoad;
1034
1035         // Download texture
1036         struct
1037         {
1038                 Move<VkDescriptorPool>                  descriptorPool;
1039                 Move<VkPipelineLayout>                  pipelineLayout;
1040                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1041                 Move<VkDescriptorSet>                   descriptorSet;
1042                 Move<VkShaderModule>                    computeModule;
1043                 Move<VkPipeline>                                computePipeline;
1044                 Move<VkImageView>                               inImageView;
1045                 VkDescriptorImageInfo                   inImageDescriptorInfo;
1046                 Move<VkSampler>                                 sampler;
1047                 Move<VkImage>                                   outImage;
1048                 Move<VkImageView>                               outImageView;
1049                 MovePtr<Allocation>                             outImageAlloc;
1050                 VkDescriptorImageInfo                   outImageDescriptorInfo;
1051         } m_dTex;
1052
1053         VkImageLayout                                           m_imageLayoutAfterUpload;
1054         VkAccessFlagBits                                        m_imageUploadAccessMask;
1055 };
1056
1057 void UploadDownloadExecutor::run(Context& context, VkBuffer buffer)
1058 {
1059         m_imageIsIntegerFormat  = isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1060         m_viewIsIntegerFormat   = isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1061
1062         m_cmdPool                               = createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1063         m_cmdBuffer                             = makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1064         beginCommandBuffer(m_vk, *m_cmdBuffer);
1065
1066         const VkImageUsageFlags         imageUsage      = getImageUsageForTestCase(m_caseDef);
1067         const VkImageCreateFlags        imageFlags      = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | (m_haveMaintenance2 ? VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0);
1068         m_image                                                                 = makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1069         m_imageAlloc                                                    = bindImage(m_vk, m_device, m_allocator, *m_image, MemoryRequirement::Any);
1070
1071         switch (m_caseDef.upload)
1072         {
1073         case UPLOAD_DRAW:
1074                 uploadDraw(context);
1075                 break;
1076         case UPLOAD_STORE:
1077                 uploadStore(context);
1078                 break;
1079         case UPLOAD_CLEAR:
1080                 uploadClear(context);
1081                 break;
1082         case UPLOAD_COPY:
1083                 uploadCopy(context);
1084                 break;
1085         default:
1086                 DE_ASSERT("Unsupported upload method");
1087         }
1088
1089         switch (m_caseDef.download)
1090         {
1091         case DOWNLOAD_COPY:
1092                 downloadCopy(context, buffer);
1093                 break;
1094         case DOWNLOAD_LOAD:
1095                 downloadLoad(context, buffer);
1096                 break;
1097         case DOWNLOAD_TEXTURE:
1098                 downloadTexture(context, buffer);
1099                 break;
1100         default:
1101                 DE_ASSERT("Unsupported download method");
1102         }
1103
1104         VK_CHECK(m_vk.endCommandBuffer(*m_cmdBuffer));
1105         submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1106 }
1107
1108 void UploadDownloadExecutor::uploadClear(Context& context)
1109 {
1110         (void) context;
1111
1112         VkImageLayout                                   requiredImageLayout     = VK_IMAGE_LAYOUT_GENERAL;
1113
1114         const VkImageSubresourceRange   subresourceRange        = makeColorSubresourceRange(0, m_caseDef.numLayers);
1115         const VkImageMemoryBarrier              imageInitBarrier        =
1116         {
1117                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
1118                 DE_NULL,                                                                                // const void*                          pNext;
1119                 0u,                                                                                             // VkAccessFlags                        srcAccessMask;
1120                 VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags                        dstAcessMask;
1121                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
1122                 requiredImageLayout,                                                    // VkImageLayout                        newLayout;
1123                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
1124                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
1125                 *m_image,                                                                               // VkImage                                      image;
1126                 subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
1127         };
1128
1129         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1130                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1131
1132         for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1133         {
1134                 const VkImageSubresourceRange   layerSubresourceRange   = makeColorSubresourceRange(layer, 1u);
1135                 const deUint32                                  colorIdx                                = layer % COLOR_TABLE_SIZE;
1136                 const VkClearColorValue                 clearColor                              = m_imageIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[colorIdx].color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1137                 m_vk.cmdClearColorImage(*m_cmdBuffer, *m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1138         }
1139
1140         m_imageLayoutAfterUpload        = requiredImageLayout;
1141         m_imageUploadAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
1142 }
1143
1144 void UploadDownloadExecutor::uploadStore(Context& context)
1145 {
1146         const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1147                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1148                 DE_NULL,                                                                                        // const void*                  pNext
1149                 VK_IMAGE_USAGE_STORAGE_BIT,                                                     // VkImageUsageFlags    usage;
1150         };
1151         m_uStore.imageView                              = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1152                                                                                                         makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1153
1154         // Setup compute pipeline
1155         m_uStore.descriptorPool                 = DescriptorPoolBuilder()
1156                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1157                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1158
1159         m_uStore.descriptorSetLayout    = DescriptorSetLayoutBuilder()
1160                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1161                 .build(m_vk, m_device);
1162
1163         m_uStore.pipelineLayout                 = makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1164         m_uStore.descriptorSet                  = makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1165         m_uStore.imageDescriptorInfo    = makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1166         m_uStore.computeModule                  = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1167         m_uStore.computePipeline                = makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1168
1169         DescriptorSetUpdateBuilder()
1170                 .writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1171                 .update(m_vk, m_device);
1172
1173         // Transition storage image for shader access (imageStore)
1174         VkImageLayout requiredImageLayout       = VK_IMAGE_LAYOUT_GENERAL;
1175         const VkImageMemoryBarrier imageBarrier =
1176         {
1177                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1178                 DE_NULL,                                                                                        // const void*                          pNext;
1179                 (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1180                 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1181                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1182                 requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1183                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1184                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1185                 *m_image,                                                                                       // VkImage                                      image;
1186                 makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1187         };
1188
1189         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1190                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1191
1192         // Dispatch
1193         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1194         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1195         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1196
1197         m_imageLayoutAfterUpload        = requiredImageLayout;
1198         m_imageUploadAccessMask         = VK_ACCESS_SHADER_WRITE_BIT;
1199 }
1200
1201 void UploadDownloadExecutor::uploadCopy(Context& context)
1202 {
1203         (void) context;
1204
1205         // Create a host-mappable buffer with the color data to upload
1206         const VkDeviceSize      pixelSize                       = tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1207         const VkDeviceSize      layerSize                       = m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1208
1209         m_uCopy.colorBufferSize                                 = layerSize * m_caseDef.numLayers;
1210         m_uCopy.colorBuffer                                             = makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1211         m_uCopy.colorBufferAlloc                                = bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1212
1213         // Fill color buffer
1214         const tcu::TextureFormat        tcuFormat       = mapVkFormat(m_caseDef.imageFormat);
1215         VkDeviceSize                            layerOffset = 0ull;
1216         for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1217         {
1218                 tcu::PixelBufferAccess  imageAccess     = tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1219                 const deUint32                  colorIdx        = layer % COLOR_TABLE_SIZE;
1220                 if (m_imageIsIntegerFormat)
1221                         tcu::clear(imageAccess, COLOR_TABLE_INT[colorIdx]);
1222                 else
1223                         tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1224                 layerOffset += layerSize;
1225         }
1226
1227         flushMappedMemoryRange(m_vk, m_device, m_uCopy.colorBufferAlloc->getMemory(), m_uCopy.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1228
1229         // Prepare buffer and image for copy
1230         const VkBufferMemoryBarrier     bufferInitBarrier       =
1231         {
1232                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                        // VkStructureType    sType;
1233                 DE_NULL,                                                                                        // const void*        pNext;
1234                 VK_ACCESS_HOST_WRITE_BIT,                                                       // VkAccessFlags      srcAccessMask;
1235                 VK_ACCESS_TRANSFER_READ_BIT,                                            // VkAccessFlags      dstAccessMask;
1236                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t           srcQueueFamilyIndex;
1237                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t           dstQueueFamilyIndex;
1238                 *m_uCopy.colorBuffer,                                                           // VkBuffer           buffer;
1239                 0ull,                                                                                           // VkDeviceSize       offset;
1240                 VK_WHOLE_SIZE,                                                                          // VkDeviceSize       size;
1241         };
1242
1243         const VkImageMemoryBarrier      imageInitBarrier        =
1244         {
1245                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1246                 DE_NULL,                                                                                        // const void*                          pNext;
1247                 0u,                                                                                                     // VkAccessFlags                        outputMask;
1248                 VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        inputMask;
1249                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1250                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
1251                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1252                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1253                 *m_image,                                                                                       // VkImage                                      image;
1254                 makeColorSubresourceRange(0, m_caseDef.numLayers)       // VkImageSubresourceRange      subresourceRange;
1255         };
1256
1257         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1258                 0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1259
1260         // Copy buffer to image
1261         const VkImageSubresourceLayers  subresource     =
1262         {
1263                 VK_IMAGE_ASPECT_COLOR_BIT,                                                      // VkImageAspectFlags    aspectMask;
1264                 0u,                                                                                                     // uint32_t              mipLevel;
1265                 0u,                                                                                                     // uint32_t              baseArrayLayer;
1266                 m_caseDef.numLayers,                                                            // uint32_t              layerCount;
1267         };
1268
1269         const VkBufferImageCopy                 region          =
1270         {
1271                 0ull,                                                                                           // VkDeviceSize                bufferOffset;
1272                 0u,                                                                                                     // uint32_t                    bufferRowLength;
1273                 0u,                                                                                                     // uint32_t                    bufferImageHeight;
1274                 subresource,                                                                            // VkImageSubresourceLayers    imageSubresource;
1275                 makeOffset3D(0, 0, 0),                                                          // VkOffset3D                  imageOffset;
1276                 makeExtent3D(m_caseDef.size),                                           // VkExtent3D                  imageExtent;
1277         };
1278
1279         m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &region);
1280
1281         const VkImageMemoryBarrier      imagePostInitBarrier    =
1282         {
1283                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1284                 DE_NULL,                                                                                        // const void*                          pNext;
1285                 VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        outputMask;
1286                 VK_ACCESS_TRANSFER_READ_BIT,                                            // VkAccessFlags                        inputMask;
1287                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        oldLayout;
1288                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
1289                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1290                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1291                 *m_image,                                                                                       // VkImage                                      image;
1292                 makeColorSubresourceRange(0, m_caseDef.numLayers)       // VkImageSubresourceRange      subresourceRange;
1293         };
1294
1295         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1296                 0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1297
1298         m_imageLayoutAfterUpload        = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1299         m_imageUploadAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
1300 }
1301
1302 void UploadDownloadExecutor::uploadDraw(Context& context)
1303 {
1304         // Create vertex buffer
1305         {
1306                 const vector<Vec4>      vertices                                = genVertexData(m_caseDef);
1307                 const VkDeviceSize      vertexBufferSize                = vertices.size() * sizeof(Vec4);
1308
1309                 m_uDraw.vertexBuffer                                            = makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1310                 m_uDraw.vertexBufferAlloc                                       = bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1311                 deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1312                 flushMappedMemoryRange(m_vk, m_device, m_uDraw.vertexBufferAlloc->getMemory(), m_uDraw.vertexBufferAlloc->getOffset(), vertexBufferSize);
1313         }
1314
1315         // Create attachments and pipelines for each image layer
1316         m_uDraw.pipelineLayout                                                  = makePipelineLayout(m_vk, m_device);
1317         m_uDraw.renderPass                                                              = makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1318         m_uDraw.vertexModule                                                    = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1319         m_uDraw.fragmentModule                                                  = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1320
1321         for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1322         {
1323                 const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1324                         VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1325                         DE_NULL,                                                                                        // const void*                  pNext
1326                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,                            // VkImageUsageFlags    usage;
1327                 };
1328                 Move<VkImageView>       imageView       = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1329                                                                                                                 makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1330                 m_uDraw.attachmentHandles.push_back(*imageView);
1331                 m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1332                 m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1333                         m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1334         }
1335
1336         // Create framebuffer
1337         m_uDraw.framebuffer     = makeFramebuffer(m_vk, m_device, *m_uDraw.renderPass, static_cast<deUint32>(m_uDraw.attachmentHandles.size()), &m_uDraw.attachmentHandles[0], m_caseDef.size.swizzle(0, 1));
1338
1339         // Create command buffer
1340         {
1341                 {
1342                         vector<VkClearValue>    clearValues             (m_caseDef.numLayers, m_viewIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[0] : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1343
1344                         const VkRect2D                  renderArea      =
1345                         {
1346                                 makeOffset2D(0, 0),
1347                                 makeExtent2D(m_caseDef.size.x(), m_caseDef.size.y()),
1348                         };
1349
1350                         const VkRenderPassBeginInfo     renderPassBeginInfo     =
1351                         {
1352                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1353                                 DE_NULL,                                                                        // const void*             pNext;
1354                                 *m_uDraw.renderPass,                                                    // VkRenderPass            renderPass;
1355                                 *m_uDraw.framebuffer,                                                   // VkFramebuffer           framebuffer;
1356                                 renderArea,                                                                     // VkRect2D                renderArea;
1357                                 static_cast<deUint32>(clearValues.size()),      // uint32_t                clearValueCount;
1358                                 &clearValues[0],                                                        // const VkClearValue*     pClearValues;
1359                         };
1360
1361                         m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1362                 }
1363
1364                 // Render
1365                 const VkDeviceSize      vertexDataPerDraw       = 4 * 2 * sizeof(Vec4);
1366                 VkDeviceSize            vertexBufferOffset      = 0ull;
1367                 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1368                 {
1369                         if (subpassNdx != 0)
1370                                 m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1371
1372                         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1373
1374                         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1375                         m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1376                         vertexBufferOffset      += vertexDataPerDraw;
1377                 }
1378
1379                 m_vk.cmdEndRenderPass(*m_cmdBuffer);
1380         }
1381
1382         m_imageLayoutAfterUpload        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1383         m_imageUploadAccessMask         = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1384 }
1385
1386 void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1387 {
1388         (void) context;
1389
1390         copyImageToBuffer(*m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1391 }
1392
1393 void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1394 {
1395         // Create output image with download result
1396         const VkImageUsageFlags usageFlags      = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1397         m_dTex.outImage                                         = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1398         m_dTex.outImageAlloc                            = bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1399         m_dTex.outImageView                                     = makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1400
1401         const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1402                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1403                 DE_NULL,                                                                                        // const void*                  pNext
1404                 VK_IMAGE_USAGE_SAMPLED_BIT,                                                     // VkImageUsageFlags    usage;
1405         };
1406         m_dTex.inImageView                                      = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1407                                                                                                                 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1408         m_dTex.sampler                                          = makeSampler(m_vk, m_device);
1409
1410         // Setup compute pipeline
1411         m_dTex.descriptorPool                           = DescriptorPoolBuilder()
1412                 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1413                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1414                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1415
1416         m_dTex.descriptorSetLayout                      = DescriptorSetLayoutBuilder()
1417                 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1418                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1419                 .build(m_vk, m_device);
1420
1421         m_dTex.pipelineLayout                           = makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1422         m_dTex.descriptorSet                            = makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1423         m_dTex.inImageDescriptorInfo            = makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1424         m_dTex.outImageDescriptorInfo           = makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1425         m_dTex.computeModule                            = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1426         m_dTex.computePipeline                          = makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1427
1428         DescriptorSetUpdateBuilder()
1429                 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1430                 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1431                 .update(m_vk, m_device);
1432
1433         // Transition images for shader access (texture / imageStore)
1434         const VkImageMemoryBarrier imageBarriers[]      =
1435         {
1436                 {
1437                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1438                         DE_NULL,                                                                                        // const void*                          pNext;
1439                         (VkAccessFlags)m_imageUploadAccessMask,                         // VkAccessFlags                        srcAccessMask;
1440                         (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,                       // VkAccessFlags                        dstAccessMask;
1441                         m_imageLayoutAfterUpload,                                                       // VkImageLayout                        oldLayout;
1442                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,                       // VkImageLayout                        newLayout;
1443                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1444                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1445                         *m_image,                                                                                       // VkImage                                      image;
1446                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1447                 },
1448                 {
1449                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1450                         DE_NULL,                                                                                        // const void*                          pNext;
1451                         (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1452                         (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1453                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1454                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        newLayout;
1455                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1456                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1457                         *m_dTex.outImage,                                                                       // VkImage                                      image;
1458                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1459                 }
1460         };
1461
1462         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1463                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1464
1465         // Dispatch
1466         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1467         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1468         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1469
1470         // Copy output image to color buffer
1471         copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1472 }
1473
1474 void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1475 {
1476         // Create output image with download result
1477         const VkImageUsageFlags usageFlags      = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1478         m_dLoad.outImage                                        = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1479         m_dLoad.outImageAlloc                           = bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1480         m_dLoad.outImageView                            = makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1481
1482         const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1483                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1484                 DE_NULL,                                                                                        // const void*                  pNext
1485                 VK_IMAGE_USAGE_STORAGE_BIT,                                                     // VkImageUsageFlags    usage;
1486         };
1487         m_dLoad.inImageView                                     = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1488                                                                                                                 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1489
1490         // Setup compute pipeline
1491         m_dLoad.descriptorPool                          = DescriptorPoolBuilder()
1492                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1493                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1494
1495         m_dLoad.descriptorSetLayout                     = DescriptorSetLayoutBuilder()
1496                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1497                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1498                 .build(m_vk, m_device);
1499
1500         m_dLoad.pipelineLayout                          = makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1501         m_dLoad.descriptorSet                           = makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1502         m_dLoad.inImageDescriptorInfo           = makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1503         m_dLoad.outImageDescriptorInfo          = makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1504         m_dLoad.computeModule                           = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1505         m_dLoad.computePipeline                         = makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1506
1507         DescriptorSetUpdateBuilder()
1508                 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1509                 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1510                 .update(m_vk, m_device);
1511
1512         // Transition storage images for shader access (imageLoad/Store)
1513         VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1514         const VkImageMemoryBarrier imageBarriers[]      =
1515         {
1516                 {
1517                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1518                         DE_NULL,                                                                                        // const void*                          pNext;
1519                         (VkAccessFlags)m_imageUploadAccessMask,                         // VkAccessFlags                        srcAccessMask;
1520                         (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,                       // VkAccessFlags                        dstAccessMask;
1521                         m_imageLayoutAfterUpload,                                                       // VkImageLayout                        oldLayout;
1522                         requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1523                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1524                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1525                         *m_image,                                                                                       // VkImage                                      image;
1526                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1527                 },
1528                 {
1529                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1530                         DE_NULL,                                                                                        // const void*                          pNext;
1531                         (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1532                         (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1533                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1534                         requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1535                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1536                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1537                         *m_dLoad.outImage,                                                                      // VkImage                                      image;
1538                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1539                 }
1540         };
1541
1542         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1543                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1544
1545         // Dispatch
1546         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1547         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1548         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1549
1550         // Copy output image to color buffer
1551         copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1552 }
1553
1554 void UploadDownloadExecutor::copyImageToBuffer(VkImage                          sourceImage,
1555                                                                                            VkBuffer                             buffer,
1556                                                                                            const IVec3                  size,
1557                                                                                            const VkAccessFlags  srcAccessMask,
1558                                                                                            const VkImageLayout  oldLayout,
1559                                                                                            const deUint32               numLayers)
1560 {
1561         // Copy result to host visible buffer for inspection
1562         const VkImageMemoryBarrier      imageBarrier    =
1563         {
1564                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
1565                 DE_NULL,                                                                        // const void*                          pNext;
1566                 srcAccessMask,                                                          // VkAccessFlags                        outputMask;
1567                 VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        inputMask;
1568                 oldLayout,                                                                      // VkImageLayout                        oldLayout;
1569                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                        newLayout;
1570                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
1571                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
1572                 sourceImage,                                                            // VkImage                                      image;
1573                 makeColorSubresourceRange(0, numLayers)         // VkImageSubresourceRange      subresourceRange;
1574         };
1575
1576         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1577                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1578
1579         const VkImageSubresourceLayers  subresource     =
1580         {
1581                 VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags    aspectMask;
1582                 0u,                                                                                     // uint32_t              mipLevel;
1583                 0u,                                                                                     // uint32_t              baseArrayLayer;
1584                 numLayers,                                                                      // uint32_t              layerCount;
1585         };
1586
1587         const VkBufferImageCopy                 region          =
1588         {
1589                 0ull,                                                                           // VkDeviceSize                bufferOffset;
1590                 0u,                                                                                     // uint32_t                    bufferRowLength;
1591                 0u,                                                                                     // uint32_t                    bufferImageHeight;
1592                 subresource,                                                            // VkImageSubresourceLayers    imageSubresource;
1593                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  imageOffset;
1594                 makeExtent3D(size),                                                     // VkExtent3D                  imageExtent;
1595         };
1596
1597         m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
1598
1599         const VkBufferMemoryBarrier     bufferBarrier =
1600         {
1601                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1602                 DE_NULL,                                                                        // const void*        pNext;
1603                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1604                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1605                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1606                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1607                 buffer,                                                                         // VkBuffer           buffer;
1608                 0ull,                                                                           // VkDeviceSize       offset;
1609                 VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1610         };
1611
1612         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1613                 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1614 }
1615
1616 bool isStorageImageExtendedFormat (const VkFormat format)
1617 {
1618         switch (format)
1619         {
1620                 case VK_FORMAT_R32G32_SFLOAT:
1621                 case VK_FORMAT_R32G32_SINT:
1622                 case VK_FORMAT_R32G32_UINT:
1623                 case VK_FORMAT_R16G16B16A16_UNORM:
1624                 case VK_FORMAT_R16G16B16A16_SNORM:
1625                 case VK_FORMAT_R16G16_SFLOAT:
1626                 case VK_FORMAT_R16G16_UNORM:
1627                 case VK_FORMAT_R16G16_SNORM:
1628                 case VK_FORMAT_R16G16_SINT:
1629                 case VK_FORMAT_R16G16_UINT:
1630                 case VK_FORMAT_R16_SFLOAT:
1631                 case VK_FORMAT_R16_UNORM:
1632                 case VK_FORMAT_R16_SNORM:
1633                 case VK_FORMAT_R16_SINT:
1634                 case VK_FORMAT_R16_UINT:
1635                 case VK_FORMAT_R8G8_UNORM:
1636                 case VK_FORMAT_R8G8_SNORM:
1637                 case VK_FORMAT_R8G8_SINT:
1638                 case VK_FORMAT_R8G8_UINT:
1639                 case VK_FORMAT_R8_UNORM:
1640                 case VK_FORMAT_R8_SNORM:
1641                 case VK_FORMAT_R8_SINT:
1642                 case VK_FORMAT_R8_UINT:
1643                         return true;
1644
1645                 default:
1646                         return false;
1647         }
1648 }
1649
1650 tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1651 {
1652         const DeviceInterface&                  vk                      = context.getDeviceInterface();
1653         const InstanceInterface&                vki                     = context.getInstanceInterface();
1654         const VkDevice                                  device          = context.getDevice();
1655         const VkPhysicalDevice                  physDevice      = context.getPhysicalDevice();
1656         Allocator&                                              allocator       = context.getDefaultAllocator();
1657
1658         // Check required features on the format for the required upload/download methods
1659         VkFormatProperties      imageFormatProps, viewFormatProps;
1660         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1661         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1662
1663         VkFormatFeatureFlags    viewFormatFeatureFlags = 0u;
1664         switch (caseDef.upload)
1665         {
1666         case UPLOAD_DRAW:
1667                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1668                 break;
1669         case UPLOAD_STORE:
1670                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1671                 break;
1672         default:
1673                 DE_ASSERT("Invalid upload method");
1674                 break;
1675         }
1676         switch (caseDef.download)
1677         {
1678         case DOWNLOAD_TEXTURE:
1679                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1680                 // For the texture case we write the samples read to a separate output image with the same view format
1681                 // so we need to check that we can also use the view format for storage
1682                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1683                 break;
1684         case DOWNLOAD_LOAD:
1685                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1686                 break;
1687         default:
1688                 DE_ASSERT("Invalid download method");
1689                 break;
1690         }
1691
1692         if ((viewFormatFeatureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) &&
1693                 isStorageImageExtendedFormat(caseDef.viewFormat) &&
1694                 !getPhysicalDeviceFeatures(vki, physDevice).shaderStorageImageExtendedFormats)
1695         {
1696                 TCU_THROW(NotSupportedError, "View format requires shaderStorageImageExtended");
1697         }
1698
1699         if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1700                 TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1701
1702         // We don't use the base image for anything other than transfer
1703         // operations so there are no features to check.  However, The Vulkan
1704         // 1.0 spec does not allow us to create an image view with usage that
1705         // is not supported by the main format.  With VK_KHR_maintenance2, we
1706         // can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1707         if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1708             !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance2"))
1709         {
1710                 TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1711         }
1712
1713         // Create a color buffer for host-inspection of results
1714         // For the Copy download method, this is the target of the download, for other
1715         // download methods, pixel data will be copied to this buffer from the download
1716         // target
1717         const VkDeviceSize                      colorBufferSize         = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1718         const Unique<VkBuffer>          colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1719         const UniquePtr<Allocation>     colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1720         deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1721         flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1722
1723         // Execute the test
1724         UploadDownloadExecutor executor(context, caseDef);
1725         executor.run(context, *colorBuffer);
1726
1727         // Verify results
1728         {
1729                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1730
1731                 // For verification purposes, we use the format of the upload to generate the expected image
1732                 const VkFormat                                          format                  = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1733                 const tcu::TextureFormat                        tcuFormat               = mapVkFormat(format);
1734                 const bool                                                      isIntegerFormat = isUintFormat(format) || isIntFormat(format);
1735                 const tcu::ConstPixelBufferAccess       resultImage             (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1736                 tcu::TextureLevel                                       textureLevel    (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1737                 const tcu::PixelBufferAccess            expectedImage   = textureLevel.getAccess();
1738                 generateExpectedImage(expectedImage, caseDef);
1739
1740                 bool ok;
1741                 if (isIntegerFormat)
1742                         ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1743                 else
1744                         ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1745                 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1746         }
1747 }
1748
1749 tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1750 {
1751         de::MovePtr<TestCaseGroup> testGroup    (new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1752         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1753         {
1754                 const Texture&                                  texture                                 = s_textures[textureNdx];
1755                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType    (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1756
1757                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1758                 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1759                 {
1760                         if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1761                         {
1762                                 for (int upload = 0; upload < UPLOAD_LAST; upload++)
1763                                 for (int download = 0; download < DOWNLOAD_LAST; download++)
1764                                 {
1765                                         const CaseDef caseDef =
1766                                         {
1767                                                 texture.type(),
1768                                                 texture.layerSize(),
1769                                                 static_cast<deUint32>(texture.numLayers()),
1770                                                 s_formats[imageFormatNdx],
1771                                                 s_formats[viewFormatNdx],
1772                                                 static_cast<enum Upload>(upload),
1773                                                 static_cast<enum Download>(download)
1774                                         };
1775
1776                                         const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1777                                                 "_" + getUploadString(upload) + "_" + getDownloadString(download);
1778                                         addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1779                                 }
1780                         }
1781                 }
1782
1783                 testGroup->addChild(groupByImageViewType.release());
1784         }
1785
1786         return testGroup.release();
1787 }
1788
1789 } // image
1790 } // vkt