Merge remote-tracking branch 'khronos/master' into deqp-dev
[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 "vktImageLoadStoreUtil.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTexture.hpp"
28
29 #include "vkBuilderUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkRef.hpp"
35 #include "vkDefs.hpp"
36 #include "vkPlatform.hpp"
37 #include "vkWsiUtil.hpp"
38 #include "vkDeviceUtil.hpp"
39
40 #include "deUniquePtr.hpp"
41 #include "deSharedPtr.hpp"
42
43 #include "tcuImageCompare.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuTextureUtil.hpp"
46 #include "tcuPlatform.hpp"
47
48 #include <string>
49 #include <vector>
50
51 using namespace vk;
52 using namespace tcu;
53 using namespace vk::wsi;
54
55 using de::UniquePtr;
56 using de::MovePtr;
57 using de::SharedPtr;
58 using std::vector;
59 using std::string;
60
61 namespace vkt
62 {
63 namespace image
64 {
65
66 typedef SharedPtr<Unique<VkPipeline> >  SharedPtrVkPipeline;
67 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
68
69 template<typename T>
70 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
71 {
72         return SharedPtr<Unique<T> >(new Unique<T>(move));
73 }
74
75 enum Upload {
76         UPLOAD_CLEAR = 0,
77         UPLOAD_COPY,
78         UPLOAD_STORE,
79         UPLOAD_DRAW,
80         UPLOAD_LAST
81 };
82
83 enum Download {
84         DOWNLOAD_COPY = 0,
85         DOWNLOAD_LOAD,
86         DOWNLOAD_TEXTURE,
87         DOWNLOAD_LAST
88 };
89
90 std::string getUploadString (const int upload)
91 {
92         const char* strs[] = { "clear", "copy", "store", "draw" };
93         return strs[upload];
94 }
95
96 std::string getDownloadString (const int download)
97 {
98         const char* strs[] = { "copy", "load", "texture" };
99         return strs[download];
100 }
101
102 struct CaseDef
103 {
104         ImageType               imageType;
105         IVec3                   size;
106         deUint32                numLayers;
107         VkFormat                imageFormat;
108         VkFormat                viewFormat;
109         enum Upload             upload;
110         enum Download   download;
111         bool                    isFormatListTest;
112         bool                    isSwapchainImageTest;
113         Type                    wsiType;
114 };
115
116 static const deUint32 COLOR_TABLE_SIZE = 4;
117
118 // Reference color values for float color rendering. Values have been chosen
119 // so that when the bit patterns are reinterpreted as a 16-bit float, we do not
120 // run into NaN / inf / denorm values.
121 static const Vec4       COLOR_TABLE_FLOAT[COLOR_TABLE_SIZE]     =
122 {
123         Vec4(0.00f, 0.40f, 0.80f, 0.10f),
124         Vec4(0.50f, 0.10f, 0.90f, 0.20f),
125         Vec4(0.20f, 0.60f, 1.00f, 0.30f),
126         Vec4(0.30f, 0.70f, 0.00f, 0.40f),
127 };
128
129 // Reference color values for integer color rendering. We avoid negative
130 // values (even for SINT formats) to avoid the situation where sign extension
131 // leads to NaN / inf values when they are reinterpreted with a float
132 // format.
133 static const IVec4      COLOR_TABLE_INT[COLOR_TABLE_SIZE]       =
134 {
135         IVec4(0x70707070, 0x3C3C3C3C, 0x65656565, 0x29292929),
136         IVec4(0x3C3C3C3C, 0x65656565, 0x29292929, 0x70707070),
137         IVec4(0x29292929, 0x70707070, 0x3C3C3C3C, 0x65656565),
138         IVec4(0x65656565, 0x29292929, 0x70707070, 0x3C3C3C3C),
139 };
140
141 // Reference clear colors created from the color table values
142 static const VkClearValue REFERENCE_CLEAR_COLOR_FLOAT[COLOR_TABLE_SIZE] =
143 {
144         makeClearValueColorF32(COLOR_TABLE_FLOAT[0].x(), COLOR_TABLE_FLOAT[0].y(), COLOR_TABLE_FLOAT[0].z(), COLOR_TABLE_FLOAT[0].w()),
145         makeClearValueColorF32(COLOR_TABLE_FLOAT[1].x(), COLOR_TABLE_FLOAT[1].y(), COLOR_TABLE_FLOAT[1].z(), COLOR_TABLE_FLOAT[1].w()),
146         makeClearValueColorF32(COLOR_TABLE_FLOAT[2].x(), COLOR_TABLE_FLOAT[2].y(), COLOR_TABLE_FLOAT[2].z(), COLOR_TABLE_FLOAT[2].w()),
147         makeClearValueColorF32(COLOR_TABLE_FLOAT[3].x(), COLOR_TABLE_FLOAT[3].y(), COLOR_TABLE_FLOAT[3].z(), COLOR_TABLE_FLOAT[3].w()),
148 };
149
150 static const Texture s_textures[] =
151 {
152         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(32, 32, 1),  1),
153         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(32, 32, 1),  4),
154 };
155
156 static VkClearValue getClearValueInt(const CaseDef& caseDef, deUint32 colorTableIndex)
157 {
158         VkClearValue            clearValue;
159         deUint32                        channelMask     = 0;
160
161         if (caseDef.upload == UPLOAD_DRAW)
162         {
163                 // We use this mask to get small color values in the vertex buffer and
164                 // avoid possible round off errors from int-to-float conversions.
165                 channelMask = 0xFFu;
166         }
167         else
168         {
169                 VkFormat                        format;
170                 tcu::TextureFormat      tcuFormat;
171
172                 // Select a mask such that no integer-based color values end up
173                 // reinterpreted as NaN/Inf/denorm values.
174                 if (caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY)
175                         format = caseDef.imageFormat;
176                 else
177                         format = caseDef.viewFormat;
178
179                 tcuFormat = mapVkFormat(format);
180
181                 switch (getChannelSize(tcuFormat.type))
182                 {
183                         case 1: // 8-bit
184                                 channelMask = 0xFFu;
185                                 break;
186                         case 2: // 16-bit
187                                 channelMask = 0xFFFFu;
188                                 break;
189                         case 4: // 32-bit
190                                 channelMask = 0xFFFFFFFFu;
191                                 break;
192                         default:
193                                 DE_ASSERT(0);
194                 }
195         }
196
197         clearValue.color.int32[0] = COLOR_TABLE_INT[colorTableIndex].x() & channelMask;
198         clearValue.color.int32[1] = COLOR_TABLE_INT[colorTableIndex].y() & channelMask;
199         clearValue.color.int32[2] = COLOR_TABLE_INT[colorTableIndex].z() & channelMask;
200         clearValue.color.int32[3] = COLOR_TABLE_INT[colorTableIndex].w() & channelMask;
201
202         return clearValue;
203 }
204
205 VkImageType getImageType (const ImageType textureImageType)
206 {
207         switch (textureImageType)
208         {
209                 case IMAGE_TYPE_2D:
210                 case IMAGE_TYPE_2D_ARRAY:
211                         return VK_IMAGE_TYPE_2D;
212
213                 default:
214                         DE_ASSERT(0);
215                         return VK_IMAGE_TYPE_LAST;
216         }
217 }
218
219 VkImageViewType getImageViewType (const ImageType textureImageType)
220 {
221         switch (textureImageType)
222         {
223                 case IMAGE_TYPE_2D:
224                         return VK_IMAGE_VIEW_TYPE_2D;
225                 case IMAGE_TYPE_2D_ARRAY:
226                         return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
227
228                 default:
229                         DE_ASSERT(0);
230                         return VK_IMAGE_VIEW_TYPE_LAST;
231         }
232 }
233
234 static const VkFormat s_formats[] =
235 {
236         VK_FORMAT_R32G32B32A32_SFLOAT,
237         VK_FORMAT_R16G16B16A16_SFLOAT,
238         VK_FORMAT_R32G32_SFLOAT,
239         VK_FORMAT_R16G16_SFLOAT,
240         VK_FORMAT_R32_SFLOAT,
241
242         VK_FORMAT_R32G32B32A32_UINT,
243         VK_FORMAT_R16G16B16A16_UINT,
244         VK_FORMAT_R8G8B8A8_UINT,
245         VK_FORMAT_R32G32_UINT,
246         VK_FORMAT_R16G16_UINT,
247         VK_FORMAT_R32_UINT,
248
249         VK_FORMAT_R32G32B32A32_SINT,
250         VK_FORMAT_R16G16B16A16_SINT,
251         VK_FORMAT_R8G8B8A8_SINT,
252         VK_FORMAT_R32G32_SINT,
253         VK_FORMAT_R16G16_SINT,
254         VK_FORMAT_R32_SINT,
255
256         VK_FORMAT_R8G8B8A8_UNORM,
257         VK_FORMAT_R8G8B8A8_SNORM,
258         VK_FORMAT_R8G8B8A8_SRGB,
259         VK_FORMAT_B8G8R8A8_UNORM,
260         VK_FORMAT_B8G8R8A8_SNORM,
261         VK_FORMAT_B8G8R8A8_SRGB,
262 };
263
264 static const VkFormat s_swapchainFormats[] =
265 {
266         VK_FORMAT_R8G8B8A8_UNORM,
267         VK_FORMAT_R8G8B8A8_SNORM,
268         VK_FORMAT_R8G8B8A8_SRGB,
269         VK_FORMAT_B8G8R8A8_UNORM,
270         VK_FORMAT_B8G8R8A8_SNORM,
271         VK_FORMAT_B8G8R8A8_SRGB,
272 };
273
274 bool isSRGBConversionRequired(const CaseDef& caseDef)
275 {
276         bool required = false;
277
278         if (isSRGB(mapVkFormat(caseDef.imageFormat)))
279         {
280                 if (caseDef.upload == UPLOAD_CLEAR)
281                 {
282                         required = true;
283                 }
284         }
285
286         if (isSRGB(mapVkFormat(caseDef.viewFormat)))
287         {
288                 if (caseDef.upload == UPLOAD_DRAW)
289                 {
290                         required = true;
291                 }
292
293                 // Following modes require VK_IMAGE_USAGE_STORAGE_BIT usage, not supported by srgb format
294                 DE_ASSERT(caseDef.upload   != UPLOAD_STORE);
295                 DE_ASSERT(caseDef.download != DOWNLOAD_LOAD);
296                 DE_ASSERT(caseDef.download != DOWNLOAD_TEXTURE);
297         }
298
299         return required;
300 }
301
302
303 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
304 {
305         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
306 }
307
308 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
309 {
310         std::ostringstream str;
311         if (numComponents == 1)
312                 str << (isUint ? "uint" : isSint ? "int" : "float");
313         else
314                 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
315
316         return str.str();
317 }
318
319 std::string getShaderSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
320 {
321         std::ostringstream samplerType;
322
323         if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
324                 samplerType << "u";
325         else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
326                 samplerType << "i";
327
328         switch (type)
329         {
330                 case VK_IMAGE_VIEW_TYPE_2D:
331                         samplerType << "sampler2D";
332                         break;
333
334                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
335                         samplerType << "sampler2DArray";
336                         break;
337
338                 default:
339                         DE_FATAL("Ivalid image view type");
340                         break;
341         }
342
343         return samplerType.str();
344 }
345
346 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
347 {
348         if (caseDef.upload == UPLOAD_DRAW)
349         {
350                 {
351                         std::ostringstream src;
352                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
353                                 << "\n"
354                                 << "layout(location = 0) in  vec4 in_position;\n"
355                                 << "layout(location = 1) in  vec4 in_color;\n"
356                                 << "layout(location = 0) out vec4 out_color;\n"
357                                 << "\n"
358                                 << "out gl_PerVertex {\n"
359                                 << "    vec4 gl_Position;\n"
360                                 << "};\n"
361                                 << "\n"
362                                 << "void main(void)\n"
363                                 << "{\n"
364                                 << "    gl_Position     = in_position;\n"
365                                 << "    out_color       = in_color;\n"
366                                 << "}\n";
367
368                         programCollection.glslSources.add("uploadDrawVert") << glu::VertexSource(src.str());
369                 }
370
371                 {
372                         const int       numComponents           = getNumUsedChannels(mapVkFormat(caseDef.viewFormat).order);
373                         const bool      isUint                          = isUintFormat(caseDef.viewFormat);
374                         const bool      isSint                          = isIntFormat(caseDef.viewFormat);
375                         const std::string colorFormat   = getColorFormatStr(numComponents, isUint, isSint);
376
377                         std::ostringstream src;
378                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
379                                 << "\n"
380                                 << "layout(location = 0) in  vec4 in_color;\n"
381                                 << "layout(location = 0) out " << colorFormat << " out_color;\n"
382                                 << "\n"
383                                 << "void main(void)\n"
384                                 << "{\n"
385                                 << "    out_color = " << colorFormat << "("
386                                 << (numComponents == 1 ? "in_color.r"   :
387                                         numComponents == 2 ? "in_color.rg"  :
388                                         numComponents == 3 ? "in_color.rgb" : "in_color")
389                                 << ");\n"
390                                 << "}\n";
391
392                         programCollection.glslSources.add("uploadDrawFrag") << glu::FragmentSource(src.str());
393                 }
394         }
395
396         if (caseDef.upload == UPLOAD_STORE)
397         {
398                 const TextureFormat     tcuFormat               = mapVkFormat(caseDef.viewFormat);
399                 const std::string       imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
400                 const std::string       imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
401                 const std::string       colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
402                 const bool                      isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
403
404                 std::ostringstream src;
405                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
406                         << "\n"
407                         << "layout (local_size_x = 1) in;\n"
408                         << "\n"
409                         << "layout(binding=0, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"
410                         << "\n"
411                         << "const " << colorTypeStr << " colorTable[] = " << colorTypeStr << "[](\n";
412                 for (deUint32 idx = 0; idx < COLOR_TABLE_SIZE; idx++)
413                 {
414                         if (isIntegerFormat)
415                         {
416                                 const VkClearValue      clearValue      = getClearValueInt(caseDef, idx);
417
418                                 src << "     " << colorTypeStr << "(" << clearValue.color.int32[0] << ", " << clearValue.color.int32[1] << ", " << clearValue.color.int32[2] << ", " << clearValue.color.int32[3] << ")";
419                         }
420                         else
421                                 src << "     " << colorTypeStr << "(" << COLOR_TABLE_FLOAT[idx].x() << ", " << COLOR_TABLE_FLOAT[idx].y() << ", " << COLOR_TABLE_FLOAT[idx].z() << ", " << COLOR_TABLE_FLOAT[idx].w() << ")";
422                         if (idx < COLOR_TABLE_SIZE - 1)
423                                 src << ",";
424                         src << "\n";
425                 }
426                 src << ");\n"
427                         << "\n"
428                         << "void main(void)\n"
429                         << "{\n";
430                 if (caseDef.imageType == IMAGE_TYPE_2D)
431                 {
432                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
433                 }
434                 else
435                 {
436                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
437                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
438                 }
439                 src << "    " << colorTypeStr << " color = colorTable[gl_GlobalInvocationID.z];\n"
440                         << "    imageStore(u_image, pos, color);\n"
441                         << "}\n";
442
443                 programCollection.glslSources.add("uploadStoreComp") << glu::ComputeSource(src.str());
444         }
445
446         if (caseDef.download == DOWNLOAD_LOAD)
447         {
448                 const TextureFormat     tcuFormat               = mapVkFormat(caseDef.viewFormat);
449                 const std::string       imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
450                 const std::string       imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
451                 const std::string       colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
452
453                 std::ostringstream src;
454                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
455                         << "\n"
456                         << "layout (local_size_x = 1) in;\n"
457                         << "\n"
458                         << "layout(binding=0, " << imageFormatStr << ") readonly uniform " << imageTypeStr << " in_image;\n"
459                         << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
460                         << "\n"
461                         << "void main(void)\n"
462                         << "{\n";
463                 if (caseDef.imageType == IMAGE_TYPE_2D)
464                 {
465                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
466                 }
467                 else
468                 {
469                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
470                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
471                 }
472                 src     << "    imageStore(out_image, pos, imageLoad(in_image, pos));\n"
473                         << "}\n";
474
475                 programCollection.glslSources.add("downloadLoadComp") << glu::ComputeSource(src.str());
476         }
477
478         if (caseDef.download == DOWNLOAD_TEXTURE)
479         {
480                 const TextureFormat             tcuFormat               = mapVkFormat(caseDef.viewFormat);
481                 const VkImageViewType   viewType                = getImageViewType(caseDef.imageType);
482                 const std::string               samplerTypeStr  = getShaderSamplerType(tcuFormat, viewType);
483                 const std::string               imageFormatStr  = getShaderImageFormatQualifier(tcuFormat);
484                 const std::string               imageTypeStr    = getShaderImageType(tcuFormat, caseDef.imageType);
485                 const std::string               colorTypeStr    = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
486
487                 std::ostringstream src;
488                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
489                         << "\n"
490                         << "layout (local_size_x = 1) in;\n"
491                         << "\n"
492                         << "layout(binding=0) uniform " << samplerTypeStr << " u_tex;\n"
493                         << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
494                         << "\n"
495                         << "void main(void)\n"
496                         << "{\n";
497                 if (caseDef.imageType == IMAGE_TYPE_2D)
498                 {
499                         src     << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
500                 }
501                 else
502                 {
503                         DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
504                         src     << "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
505                 }
506                 src     << "    imageStore(out_image, pos, texelFetch(u_tex, pos, 0));\n"
507                         << "}\n";
508
509                 programCollection.glslSources.add("downloadTextureComp") << glu::ComputeSource(src.str());
510         }
511 }
512
513 Move<VkImage> makeImage (const DeviceInterface&         vk,
514                                                  const VkDevice                         device,
515                                                  VkImageCreateFlags                     flags,
516                                                  VkImageType                            imageType,
517                                                  const VkFormat                         format,
518                                                  const VkFormat                         viewFormat,
519                                                  const bool                                     useImageFormatList,
520                                                  const IVec3&                           size,
521                                                  const deUint32                         numMipLevels,
522                                                  const deUint32                         numLayers,
523                                                  const VkImageUsageFlags        usage)
524 {
525         const VkFormat formatList[2] =
526         {
527                 format,
528                 viewFormat
529         };
530
531         const VkImageFormatListCreateInfoKHR formatListInfo =
532         {
533                 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,    // VkStructureType                      sType;
534                 DE_NULL,                                                                                                // const void*                          pNext;
535                 2u,                                                                                                             // deUint32                                     viewFormatCount
536                 formatList                                                                                              // const VkFormat*                      pViewFormats
537         };
538
539         const VkImageCreateInfo imageParams =
540         {
541                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType                      sType;
542                 useImageFormatList ? &formatListInfo : DE_NULL,                 // const void*                          pNext;
543                 flags,                                                                                                  // VkImageCreateFlags           flags;
544                 imageType,                                                                                              // VkImageType                          imageType;
545                 format,                                                                                                 // VkFormat                                     format;
546                 makeExtent3D(size),                                                                             // VkExtent3D                           extent;
547                 numMipLevels,                                                                                   // deUint32                                     mipLevels;
548                 numLayers,                                                                                              // deUint32                                     arrayLayers;
549                 VK_SAMPLE_COUNT_1_BIT,                                                                  // VkSampleCountFlagBits        samples;
550                 VK_IMAGE_TILING_OPTIMAL,                                                                // VkImageTiling                        tiling;
551                 usage,                                                                                                  // VkImageUsageFlags            usage;
552                 VK_SHARING_MODE_EXCLUSIVE,                                                              // VkSharingMode                        sharingMode;
553                 0u,                                                                                                             // deUint32                                     queueFamilyIndexCount;
554                 DE_NULL,                                                                                                // const deUint32*                      pQueueFamilyIndices;
555                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                        initialLayout;
556         };
557         return createImage(vk, device, &imageParams);
558 }
559
560 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
561 {
562         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
563         return createBuffer(vk, device, &bufferCreateInfo);
564 }
565
566 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
567 {
568         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
569 }
570
571 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
572 {
573         const VkSamplerCreateInfo samplerParams =
574         {
575                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
576                 DE_NULL,                                                                        // const void*                          pNext;
577                 (VkSamplerCreateFlags)0,                                        // VkSamplerCreateFlags         flags;
578                 VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter;
579                 VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
580                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
581                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
582                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
583                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
584                 0.0f,                                                                           // float                                        mipLodBias;
585                 VK_FALSE,                                                                       // VkBool32                                     anisotropyEnable;
586                 1.0f,                                                                           // float                                        maxAnisotropy;
587                 VK_FALSE,                                                                       // VkBool32                                     compareEnable;
588                 VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp                          compareOp;
589                 0.0f,                                                                           // float                                        minLod;
590                 0.0f,                                                                           // float                                        maxLod;
591                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // VkBorderColor                        borderColor;
592                 VK_FALSE,                                                                       // VkBool32                                     unnormalizedCoordinates;
593         };
594
595         return createSampler(vk, device, &samplerParams);
596 }
597
598
599 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&       vk,
600                                                                                    const VkDevice                       device)
601 {
602         const VkPipelineLayoutCreateInfo info =
603         {
604                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
605                 DE_NULL,
606                 (VkPipelineLayoutCreateFlags)0,
607                 0u,
608                 DE_NULL,
609                 0u,
610                 DE_NULL,
611         };
612         return createPipelineLayout(vk, device, &info);
613 }
614
615 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
616                                                                            const VkDevice                               device,
617                                                                            const VkPipelineLayout               pipelineLayout,
618                                                                            const VkRenderPass                   renderPass,
619                                                                            const VkShaderModule                 vertexModule,
620                                                                            const VkShaderModule                 fragmentModule,
621                                                                            const IVec2&                                 renderSize,
622                                                                            const VkPrimitiveTopology    topology,
623                                                                            const deUint32                               subpass)
624 {
625         const std::vector<VkViewport>                   viewports                                                       (1, makeViewport(renderSize));
626         const std::vector<VkRect2D>                             scissors                                                        (1, makeRect2D(renderSize));
627
628         const VkVertexInputBindingDescription   vertexInputBindingDescription           =
629         {
630                 0u,                                                                     // deUint32                             binding;
631                 (deUint32)(2 * sizeof(Vec4)),           // deUint32                             stride;
632                 VK_VERTEX_INPUT_RATE_VERTEX,            // VkVertexInputRate    inputRate;
633         };
634
635         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[]      =
636         {
637                 {
638                         0u,                                                             // deUint32                     location;
639                         0u,                                                             // deUint32                     binding;
640                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
641                         0u,                                                             // deUint32                     offset;
642                 },
643                 {
644                         1u,                                                             // deUint32                     location;
645                         0u,                                                             // deUint32                     binding;
646                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
647                         (deUint32)sizeof(Vec4),                 // deUint32                     offset;
648                 }
649         };
650
651         const VkPipelineVertexInputStateCreateInfo      vertexInputStateCreateInfo      =
652         {
653                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                             sType;
654                 DE_NULL,                                                                                                        // const void*                                 pNext;
655                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags       flags;
656                 1u,                                                                                                                     // deUint32                                    vertexBindingDescriptionCount;
657                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
658                 2u,                                                                                                                     // deUint32                                    vertexAttributeDescriptionCount;
659                 vertexInputAttributeDescriptions                                                        // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
660         };
661
662         return vk::makeGraphicsPipeline(vk,                                                                     // const DeviceInterface&                        vk
663                                                                         device,                                                         // const VkDevice                                device
664                                                                         pipelineLayout,                                         // const VkPipelineLayout                        pipelineLayout
665                                                                         vertexModule,                                           // const VkShaderModule                          vertexShaderModule
666                                                                         DE_NULL,                                                        // const VkShaderModule                          tessellationControlModule
667                                                                         DE_NULL,                                                        // const VkShaderModule                          tessellationEvalModule
668                                                                         DE_NULL,                                                        // const VkShaderModule                          geometryShaderModule
669                                                                         fragmentModule,                                         // const VkShaderModule                          fragmentShaderModule
670                                                                         renderPass,                                                     // const VkRenderPass                            renderPass
671                                                                         viewports,                                                      // const std::vector<VkViewport>&                viewports
672                                                                         scissors,                                                       // const std::vector<VkRect2D>&                  scissors
673                                                                         topology,                                                       // const VkPrimitiveTopology                     topology
674                                                                         subpass,                                                        // const deUint32                                subpass
675                                                                         0u,                                                                     // const deUint32                                patchControlPoints
676                                                                         &vertexInputStateCreateInfo);           // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
677 }
678
679 Move<VkPipeline> makeComputePipeline (const DeviceInterface&            vk,
680                                                                           const VkDevice                                device,
681                                                                           const VkPipelineLayout                pipelineLayout,
682                                                                           const VkShaderModule                  shaderModule,
683                                                                           const VkSpecializationInfo*   specInfo)
684 {
685         const VkPipelineShaderStageCreateInfo shaderStageInfo =
686         {
687                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
688                 DE_NULL,                                                                                                // const void*                                          pNext;
689                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags     flags;
690                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                        stage;
691                 shaderModule,                                                                                   // VkShaderModule                                       module;
692                 "main",                                                                                                 // const char*                                          pName;
693                 specInfo,                                                                                               // const VkSpecializationInfo*          pSpecializationInfo;
694         };
695         const VkComputePipelineCreateInfo pipelineInfo =
696         {
697                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // VkStructureType                                      sType;
698                 DE_NULL,                                                                                                // const void*                                          pNext;
699                 (VkPipelineCreateFlags)0,                                                               // VkPipelineCreateFlags                        flags;
700                 shaderStageInfo,                                                                                // VkPipelineShaderStageCreateInfo      stage;
701                 pipelineLayout,                                                                                 // VkPipelineLayout                                     layout;
702                 DE_NULL,                                                                                                // VkPipeline                                           basePipelineHandle;
703                 0,                                                                                                              // deInt32                                                      basePipelineIndex;
704         };
705         return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
706 }
707
708 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
709                                                                    const VkDevice                       device,
710                                                                    const VkFormat                       colorFormat,
711                                                                    const deUint32                       numLayers)
712 {
713         const VkAttachmentDescription colorAttachmentDescription =
714         {
715                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
716                 colorFormat,                                                                            // VkFormat                                                     format;
717                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
718                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
719                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
720                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
721                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
722                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
723                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
724         };
725         vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
726
727         // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
728         vector<VkAttachmentReference>   colorAttachmentReferences       (numLayers);
729         vector<VkSubpassDescription>    subpasses;
730
731         // Ordering here must match the framebuffer attachments
732         for (deUint32 i = 0; i < numLayers; ++i)
733         {
734                 const VkAttachmentReference attachmentRef =
735                 {
736                         i,                                                                                                      // deUint32                     attachment;
737                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
738                 };
739
740                 colorAttachmentReferences[i]    = attachmentRef;
741
742                 const VkSubpassDescription              subpassDescription      =
743                 {
744                         (VkSubpassDescriptionFlags)0,                                   // VkSubpassDescriptionFlags            flags;
745                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // VkPipelineBindPoint                          pipelineBindPoint;
746                         0u,                                                                                             // deUint32                                                     inputAttachmentCount;
747                         DE_NULL,                                                                                // const VkAttachmentReference*         pInputAttachments;
748                         1u,                                                                                             // deUint32                                                     colorAttachmentCount;
749                         &colorAttachmentReferences[i],                                  // const VkAttachmentReference*         pColorAttachments;
750                         DE_NULL,                                                                                // const VkAttachmentReference*         pResolveAttachments;
751                         DE_NULL,                                                                                // const VkAttachmentReference*         pDepthStencilAttachment;
752                         0u,                                                                                             // deUint32                                                     preserveAttachmentCount;
753                         DE_NULL                                                                                 // const deUint32*                                      pPreserveAttachments;
754                 };
755                 subpasses.push_back(subpassDescription);
756         }
757
758         const VkRenderPassCreateInfo renderPassInfo =
759         {
760                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
761                 DE_NULL,                                                                                                // const void*                                          pNext;
762                 (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
763                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
764                 &attachmentDescriptions[0],                                                             // const VkAttachmentDescription*       pAttachments;
765                 static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
766                 &subpasses[0],                                                                                  // const VkSubpassDescription*          pSubpasses;
767                 0u,                                                                                                             // deUint32                                                     dependencyCount;
768                 DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
769         };
770
771         return createRenderPass(vk, device, &renderPassInfo);
772 }
773
774 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&     vk,
775                                                                          const VkDevice                 device,
776                                                                          const VkRenderPass             renderPass,
777                                                                          const deUint32                 attachmentCount,
778                                                                          const VkImageView*             pAttachments,
779                                                                          const IVec2                    size)
780 {
781         const VkFramebufferCreateInfo framebufferInfo =
782         {
783                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
784                 DE_NULL,
785                 (VkFramebufferCreateFlags)0,
786                 renderPass,
787                 attachmentCount,
788                 pAttachments,
789                 static_cast<deUint32>(size.x()),
790                 static_cast<deUint32>(size.y()),
791                 1u,
792         };
793
794         return createFramebuffer(vk, device, &framebufferInfo);
795 }
796
797 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
798 {
799         return allocateCommandBuffer(vk, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
800 }
801
802 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
803 {
804         MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
805         VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
806         return alloc;
807 }
808
809 MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
810 {
811         MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
812         VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
813         return alloc;
814 }
815
816 vector<Vec4> genVertexData (const CaseDef& caseDef)
817 {
818         vector<Vec4>    vectorData;
819         const bool              isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
820
821         for (deUint32 z = 0; z < caseDef.numLayers; z++)
822         {
823                 const deUint32  colorIdx        = z % COLOR_TABLE_SIZE;
824                 Vec4                    color;
825
826                 if (isIntegerFormat)
827                 {
828                         const VkClearValue      clearValue      = getClearValueInt(caseDef, colorIdx);
829                         const IVec4                     colorInt        (clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
830
831                         color = colorInt.cast<float>();
832                 }
833                 else
834                 {
835                         color = COLOR_TABLE_FLOAT[colorIdx];
836                 }
837
838                 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
839                 vectorData.push_back(color);
840                 vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
841                 vectorData.push_back(color);
842                 vectorData.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
843                 vectorData.push_back(color);
844                 vectorData.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
845                 vectorData.push_back(color);
846         }
847
848         return vectorData;
849 }
850
851 void generateExpectedImage(const tcu::PixelBufferAccess& image, const CaseDef& caseDef)
852 {
853         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(image.getFormat().type);
854         const bool                                              isIntegerFormat = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
855         const IVec2                                             size                    = caseDef.size.swizzle(0, 1);
856
857         for (int z = 0; z < static_cast<int>(caseDef.numLayers); z++)
858         {
859                 const deUint32  colorIdx        = z % COLOR_TABLE_SIZE;
860                 for (int y = 0; y < size.y(); y++)
861                 for (int x = 0; x < size.x(); x++)
862                 {
863                         if (isIntegerFormat)
864                         {
865                                 const VkClearValue      clearValue      = getClearValueInt(caseDef, colorIdx);
866                                 const IVec4                     colorInt        (clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
867
868                                 image.setPixel(colorInt, x, y, z);
869                         }
870                         else
871                                 if(isSRGBConversionRequired(caseDef))
872                                         image.setPixel(tcu::linearToSRGB(COLOR_TABLE_FLOAT[colorIdx]), x, y, z);
873                                 else
874                                         image.setPixel(COLOR_TABLE_FLOAT[colorIdx], x, y, z);
875                 }
876         }
877 }
878
879 VkImageUsageFlags getImageUsageForTestCase (const CaseDef& caseDef)
880 {
881         VkImageUsageFlags flags = 0u;
882
883         switch (caseDef.upload)
884         {
885         case UPLOAD_CLEAR:
886                 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
887                 break;
888         case UPLOAD_DRAW:
889                 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
890                 break;
891         case UPLOAD_STORE:
892                 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
893                 break;
894         case UPLOAD_COPY:
895                 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
896                 break;
897         default:
898                 DE_FATAL("Invalid upload method");
899                 break;
900         }
901
902         switch (caseDef.download)
903         {
904         case DOWNLOAD_TEXTURE:
905                 flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
906                 break;
907         case DOWNLOAD_LOAD:
908                 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
909                 break;
910         case DOWNLOAD_COPY:
911                 flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
912                 break;
913         default:
914                 DE_FATAL("Invalid download method");
915                 break;
916         }
917
918         // We can only create a view for the image if it is going to be used for any of these usages,
919         // so let's make sure that we have at least one of them.
920         VkImageUsageFlags viewRequiredFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
921         if (!(flags & viewRequiredFlags))
922                 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
923
924         return flags;
925 }
926
927 // Executes a combination of upload/download methods
928 class UploadDownloadExecutor
929 {
930 public:
931         UploadDownloadExecutor(Context& context, const CaseDef& caseSpec) :
932         m_caseDef(caseSpec),
933         m_haveMaintenance2(isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance2")),
934         m_vk(context.getDeviceInterface()),
935         m_device(context.getDevice()),
936         m_queue(context.getUniversalQueue()),
937         m_queueFamilyIndex(context.getUniversalQueueFamilyIndex()),
938         m_allocator(context.getDefaultAllocator())
939         {
940         }
941
942         void runSwapchain(Context& context, VkBuffer buffer, VkImage image);
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         VkImage                                                         m_image;
980         Move<VkImage>                                           m_imageHolder;
981         MovePtr<Allocation>                                     m_imageAlloc;
982
983         // Upload copy
984         struct
985         {
986                 Move<VkBuffer>                                  colorBuffer;
987                 VkDeviceSize                                    colorBufferSize;
988                 MovePtr<Allocation>                             colorBufferAlloc;
989         } m_uCopy;
990
991         // Upload draw
992         struct
993         {
994                 Move<VkBuffer>                                  vertexBuffer;
995                 MovePtr<Allocation>                             vertexBufferAlloc;
996                 Move<VkPipelineLayout>                  pipelineLayout;
997                 Move<VkRenderPass>                              renderPass;
998                 Move<VkShaderModule>                    vertexModule;
999                 Move<VkShaderModule>                    fragmentModule;
1000                 vector<SharedPtrVkImageView>    attachments;
1001                 vector<VkImageView>                             attachmentHandles;
1002                 vector<SharedPtrVkPipeline>             pipelines;
1003                 Move<VkFramebuffer>                             framebuffer;
1004         } m_uDraw;
1005
1006         // Upload store
1007         struct
1008         {
1009                 Move<VkDescriptorPool>                  descriptorPool;
1010                 Move<VkPipelineLayout>                  pipelineLayout;
1011                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1012                 Move<VkDescriptorSet>                   descriptorSet;
1013                 VkDescriptorImageInfo                   imageDescriptorInfo;
1014                 Move<VkShaderModule>                    computeModule;
1015                 Move<VkPipeline>                                computePipeline;
1016                 Move<VkImageView>                               imageView;
1017         } m_uStore;
1018
1019         // Download load
1020         struct
1021         {
1022                 Move<VkDescriptorPool>                  descriptorPool;
1023                 Move<VkPipelineLayout>                  pipelineLayout;
1024                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1025                 Move<VkDescriptorSet>                   descriptorSet;
1026                 Move<VkShaderModule>                    computeModule;
1027                 Move<VkPipeline>                                computePipeline;
1028                 Move<VkImageView>                               inImageView;
1029                 VkDescriptorImageInfo                   inImageDescriptorInfo;
1030                 Move<VkImage>                                   outImage;
1031                 Move<VkImageView>                               outImageView;
1032                 MovePtr<Allocation>                             outImageAlloc;
1033                 VkDescriptorImageInfo                   outImageDescriptorInfo;
1034         } m_dLoad;
1035
1036         // Download texture
1037         struct
1038         {
1039                 Move<VkDescriptorPool>                  descriptorPool;
1040                 Move<VkPipelineLayout>                  pipelineLayout;
1041                 Move<VkDescriptorSetLayout>             descriptorSetLayout;
1042                 Move<VkDescriptorSet>                   descriptorSet;
1043                 Move<VkShaderModule>                    computeModule;
1044                 Move<VkPipeline>                                computePipeline;
1045                 Move<VkImageView>                               inImageView;
1046                 VkDescriptorImageInfo                   inImageDescriptorInfo;
1047                 Move<VkSampler>                                 sampler;
1048                 Move<VkImage>                                   outImage;
1049                 Move<VkImageView>                               outImageView;
1050                 MovePtr<Allocation>                             outImageAlloc;
1051                 VkDescriptorImageInfo                   outImageDescriptorInfo;
1052         } m_dTex;
1053
1054         VkImageLayout                                           m_imageLayoutAfterUpload;
1055         VkAccessFlagBits                                        m_imageUploadAccessMask;
1056 };
1057
1058
1059 void UploadDownloadExecutor::runSwapchain(Context& context, VkBuffer buffer, VkImage image)
1060 {
1061         m_imageIsIntegerFormat = isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1062         m_viewIsIntegerFormat = isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1063
1064         m_cmdPool = createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1065         m_cmdBuffer = makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1066         beginCommandBuffer(m_vk, *m_cmdBuffer);
1067
1068         m_image = image;
1069
1070         switch (m_caseDef.upload)
1071         {
1072         case UPLOAD_DRAW:
1073                 uploadDraw(context);
1074                 break;
1075         case UPLOAD_STORE:
1076                 uploadStore(context);
1077                 break;
1078         case UPLOAD_CLEAR:
1079                 uploadClear(context);
1080                 break;
1081         case UPLOAD_COPY:
1082                 uploadCopy(context);
1083                 break;
1084         default:
1085                 DE_FATAL("Unsupported upload method");
1086         }
1087
1088         switch (m_caseDef.download)
1089         {
1090         case DOWNLOAD_COPY:
1091                 downloadCopy(context, buffer);
1092                 break;
1093         case DOWNLOAD_LOAD:
1094                 downloadLoad(context, buffer);
1095                 break;
1096         case DOWNLOAD_TEXTURE:
1097                 downloadTexture(context, buffer);
1098                 break;
1099         default:
1100                 DE_FATAL("Unsupported download method");
1101         }
1102
1103         endCommandBuffer(m_vk, *m_cmdBuffer);
1104         submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1105
1106 }
1107
1108 void UploadDownloadExecutor::run(Context& context, VkBuffer buffer)
1109 {
1110         m_imageIsIntegerFormat  = isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1111         m_viewIsIntegerFormat   = isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1112
1113         m_cmdPool                               = createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1114         m_cmdBuffer                             = makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1115         beginCommandBuffer(m_vk, *m_cmdBuffer);
1116
1117         const VkImageUsageFlags         imageUsage      = getImageUsageForTestCase(m_caseDef);
1118         const VkImageCreateFlags        imageFlags      = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | (m_haveMaintenance2 ? VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0);
1119
1120         m_imageHolder                                                   = makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.viewFormat,
1121                                                                                                                 m_caseDef.isFormatListTest, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1122         m_image                                                                 = *m_imageHolder;
1123         m_imageAlloc                                                    = bindImage(m_vk, m_device, m_allocator, m_image, MemoryRequirement::Any);
1124
1125         switch (m_caseDef.upload)
1126         {
1127         case UPLOAD_DRAW:
1128                 uploadDraw(context);
1129                 break;
1130         case UPLOAD_STORE:
1131                 uploadStore(context);
1132                 break;
1133         case UPLOAD_CLEAR:
1134                 uploadClear(context);
1135                 break;
1136         case UPLOAD_COPY:
1137                 uploadCopy(context);
1138                 break;
1139         default:
1140                 DE_FATAL("Unsupported upload method");
1141         }
1142
1143         switch (m_caseDef.download)
1144         {
1145         case DOWNLOAD_COPY:
1146                 downloadCopy(context, buffer);
1147                 break;
1148         case DOWNLOAD_LOAD:
1149                 downloadLoad(context, buffer);
1150                 break;
1151         case DOWNLOAD_TEXTURE:
1152                 downloadTexture(context, buffer);
1153                 break;
1154         default:
1155                 DE_FATAL("Unsupported download method");
1156         }
1157
1158         endCommandBuffer(m_vk, *m_cmdBuffer);
1159         submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1160 }
1161
1162 void UploadDownloadExecutor::uploadClear(Context& context)
1163 {
1164         (void) context;
1165
1166         VkImageLayout                                   requiredImageLayout     = VK_IMAGE_LAYOUT_GENERAL;
1167
1168         const VkImageSubresourceRange   subresourceRange        = makeColorSubresourceRange(0, m_caseDef.numLayers);
1169         const VkImageMemoryBarrier              imageInitBarrier        =
1170         {
1171                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
1172                 DE_NULL,                                                                                // const void*                          pNext;
1173                 0u,                                                                                             // VkAccessFlags                        srcAccessMask;
1174                 VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags                        dstAcessMask;
1175                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
1176                 requiredImageLayout,                                                    // VkImageLayout                        newLayout;
1177                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
1178                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
1179                 m_image,                                                                                // VkImage                                      image;
1180                 subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
1181         };
1182
1183         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1184                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1185
1186         for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1187         {
1188                 const VkImageSubresourceRange   layerSubresourceRange   = makeColorSubresourceRange(layer, 1u);
1189                 const deUint32                                  colorIdx                                = layer % COLOR_TABLE_SIZE;
1190                 const VkClearColorValue                 clearColor                              = m_imageIsIntegerFormat ? getClearValueInt(m_caseDef, colorIdx).color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1191                 m_vk.cmdClearColorImage(*m_cmdBuffer, m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1192         }
1193
1194         m_imageLayoutAfterUpload        = requiredImageLayout;
1195         m_imageUploadAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
1196 }
1197
1198 void UploadDownloadExecutor::uploadStore(Context& context)
1199 {
1200         const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1201         {
1202                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1203                 DE_NULL,                                                                                        // const void*                  pNext
1204                 VK_IMAGE_USAGE_STORAGE_BIT,                                                     // VkImageUsageFlags    usage;
1205         };
1206         m_uStore.imageView                              = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1207                                                                                                         makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1208
1209         // Setup compute pipeline
1210         m_uStore.descriptorPool                 = DescriptorPoolBuilder()
1211                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1212                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1213
1214         m_uStore.descriptorSetLayout    = DescriptorSetLayoutBuilder()
1215                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1216                 .build(m_vk, m_device);
1217
1218         m_uStore.pipelineLayout                 = makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1219         m_uStore.descriptorSet                  = makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1220         m_uStore.imageDescriptorInfo    = makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1221         m_uStore.computeModule                  = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1222         m_uStore.computePipeline                = makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1223
1224         DescriptorSetUpdateBuilder()
1225                 .writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1226                 .update(m_vk, m_device);
1227
1228         // Transition storage image for shader access (imageStore)
1229         VkImageLayout requiredImageLayout       = VK_IMAGE_LAYOUT_GENERAL;
1230         const VkImageMemoryBarrier imageBarrier =
1231         {
1232                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1233                 DE_NULL,                                                                                        // const void*                          pNext;
1234                 (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1235                 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1236                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1237                 requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1238                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1239                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1240                 m_image,                                                                                        // VkImage                                      image;
1241                 makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1242         };
1243
1244         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1245                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1246
1247         // Dispatch
1248         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1249         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1250         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1251
1252         m_imageLayoutAfterUpload        = requiredImageLayout;
1253         m_imageUploadAccessMask         = VK_ACCESS_SHADER_WRITE_BIT;
1254 }
1255
1256 void UploadDownloadExecutor::uploadCopy(Context& context)
1257 {
1258         (void) context;
1259
1260         // Create a host-mappable buffer with the color data to upload
1261         const VkDeviceSize      pixelSize                       = tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1262         const VkDeviceSize      layerSize                       = m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1263
1264         m_uCopy.colorBufferSize                                 = layerSize * m_caseDef.numLayers;
1265         m_uCopy.colorBuffer                                             = makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1266         m_uCopy.colorBufferAlloc                                = bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1267
1268         // Fill color buffer
1269         const tcu::TextureFormat        tcuFormat       = mapVkFormat(m_caseDef.imageFormat);
1270         VkDeviceSize                            layerOffset = 0ull;
1271         for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1272         {
1273                 tcu::PixelBufferAccess  imageAccess     = tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1274                 const deUint32                  colorIdx        = layer % COLOR_TABLE_SIZE;
1275                 if (m_imageIsIntegerFormat)
1276                 {
1277                         const VkClearValue      clearValue      = getClearValueInt(m_caseDef, colorIdx);
1278                         const IVec4                     colorInt        (clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
1279
1280                         tcu::clear(imageAccess, colorInt);
1281                 }
1282                 else
1283                         tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1284                 layerOffset += layerSize;
1285         }
1286
1287         flushAlloc(m_vk, m_device, *(m_uCopy.colorBufferAlloc));
1288
1289         // Prepare buffer and image for copy
1290         const VkBufferMemoryBarrier     bufferInitBarrier       =
1291         {
1292                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                        // VkStructureType    sType;
1293                 DE_NULL,                                                                                        // const void*        pNext;
1294                 VK_ACCESS_HOST_WRITE_BIT,                                                       // VkAccessFlags      srcAccessMask;
1295                 VK_ACCESS_TRANSFER_READ_BIT,                                            // VkAccessFlags      dstAccessMask;
1296                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32           srcQueueFamilyIndex;
1297                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32           dstQueueFamilyIndex;
1298                 *m_uCopy.colorBuffer,                                                           // VkBuffer           buffer;
1299                 0ull,                                                                                           // VkDeviceSize       offset;
1300                 VK_WHOLE_SIZE,                                                                          // VkDeviceSize       size;
1301         };
1302
1303         const VkImageMemoryBarrier      imageInitBarrier        =
1304         {
1305                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1306                 DE_NULL,                                                                                        // const void*                          pNext;
1307                 0u,                                                                                                     // VkAccessFlags                        srcAccessMask;
1308                 VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        dstAccessMask;
1309                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1310                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
1311                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1312                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1313                 m_image,                                                                                        // VkImage                                      image;
1314                 makeColorSubresourceRange(0, m_caseDef.numLayers)       // VkImageSubresourceRange      subresourceRange;
1315         };
1316
1317         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1318                 0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1319
1320         // Copy buffer to image
1321         const VkImageSubresourceLayers  subresource     =
1322         {
1323                 VK_IMAGE_ASPECT_COLOR_BIT,                                                      // VkImageAspectFlags    aspectMask;
1324                 0u,                                                                                                     // deUint32              mipLevel;
1325                 0u,                                                                                                     // deUint32              baseArrayLayer;
1326                 m_caseDef.numLayers,                                                            // deUint32              layerCount;
1327         };
1328
1329         const VkBufferImageCopy                 region          =
1330         {
1331                 0ull,                                                                                           // VkDeviceSize                bufferOffset;
1332                 0u,                                                                                                     // deUint32                    bufferRowLength;
1333                 0u,                                                                                                     // deUint32                    bufferImageHeight;
1334                 subresource,                                                                            // VkImageSubresourceLayers    imageSubresource;
1335                 makeOffset3D(0, 0, 0),                                                          // VkOffset3D                  imageOffset;
1336                 makeExtent3D(m_caseDef.size),                                           // VkExtent3D                  imageExtent;
1337         };
1338
1339         m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &region);
1340
1341         const VkImageMemoryBarrier      imagePostInitBarrier    =
1342         {
1343                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1344                 DE_NULL,                                                                                        // const void*                          pNext;
1345                 VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        srcAccessMask;
1346                 VK_ACCESS_TRANSFER_READ_BIT,                                            // VkAccessFlags                        dstAccessMask;
1347                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        oldLayout;
1348                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
1349                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1350                 VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1351                 m_image,                                                                                        // VkImage                                      image;
1352                 makeColorSubresourceRange(0, m_caseDef.numLayers)       // VkImageSubresourceRange      subresourceRange;
1353         };
1354
1355         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1356                 0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1357
1358         m_imageLayoutAfterUpload        = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1359         m_imageUploadAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
1360 }
1361
1362 void UploadDownloadExecutor::uploadDraw(Context& context)
1363 {
1364         // Create vertex buffer
1365         {
1366                 const vector<Vec4>      vertices                                = genVertexData(m_caseDef);
1367                 const VkDeviceSize      vertexBufferSize                = vertices.size() * sizeof(Vec4);
1368
1369                 m_uDraw.vertexBuffer                                            = makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1370                 m_uDraw.vertexBufferAlloc                                       = bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1371                 deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1372                 flushAlloc(m_vk, m_device, *(m_uDraw.vertexBufferAlloc));
1373         }
1374
1375         // Create attachments and pipelines for each image layer
1376         m_uDraw.pipelineLayout                                                  = makePipelineLayout(m_vk, m_device);
1377         m_uDraw.renderPass                                                              = makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1378         m_uDraw.vertexModule                                                    = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1379         m_uDraw.fragmentModule                                                  = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1380
1381         for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1382         {
1383                 const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1384                 {
1385                         VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1386                         DE_NULL,                                                                                        // const void*                  pNext
1387                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,                            // VkImageUsageFlags    usage;
1388                 };
1389                 Move<VkImageView>       imageView       = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1390                                                                                                                 makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1391                 m_uDraw.attachmentHandles.push_back(*imageView);
1392                 m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1393                 m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1394                         m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1395         }
1396
1397         // Create framebuffer
1398         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));
1399
1400         // Create command buffer
1401         {
1402                 {
1403                         vector<VkClearValue>    clearValues             (m_caseDef.numLayers, m_viewIsIntegerFormat ? getClearValueInt(m_caseDef, 0) : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1404
1405                         beginRenderPass(m_vk, *m_cmdBuffer, *m_uDraw.renderPass, *m_uDraw.framebuffer, makeRect2D(0, 0, m_caseDef.size.x(), m_caseDef.size.y()), (deUint32)clearValues.size(), &clearValues[0]);
1406                 }
1407
1408                 // Render
1409                 const VkDeviceSize      vertexDataPerDraw       = 4 * 2 * sizeof(Vec4);
1410                 VkDeviceSize            vertexBufferOffset      = 0ull;
1411                 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1412                 {
1413                         if (subpassNdx != 0)
1414                                 m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1415
1416                         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1417
1418                         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1419                         m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1420                         vertexBufferOffset      += vertexDataPerDraw;
1421                 }
1422
1423                 endRenderPass(m_vk, *m_cmdBuffer);
1424         }
1425
1426         m_imageLayoutAfterUpload        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1427         m_imageUploadAccessMask         = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1428 }
1429
1430 void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1431 {
1432         (void) context;
1433
1434         copyImageToBuffer(m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1435 }
1436
1437 void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1438 {
1439         // Create output image with download result
1440         const VkImageUsageFlags usageFlags      = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1441         m_dTex.outImage                                         = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1442         m_dTex.outImageAlloc                            = bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1443         m_dTex.outImageView                                     = makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1444
1445         const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1446         {
1447                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1448                 DE_NULL,                                                                                        // const void*                  pNext
1449                 VK_IMAGE_USAGE_SAMPLED_BIT,                                                     // VkImageUsageFlags    usage;
1450         };
1451         m_dTex.inImageView                                      = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1452                                                                                                                 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1453         m_dTex.sampler                                          = makeSampler(m_vk, m_device);
1454
1455         // Setup compute pipeline
1456         m_dTex.descriptorPool                           = DescriptorPoolBuilder()
1457                 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1458                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1459                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1460
1461         m_dTex.descriptorSetLayout                      = DescriptorSetLayoutBuilder()
1462                 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1463                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1464                 .build(m_vk, m_device);
1465
1466         m_dTex.pipelineLayout                           = makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1467         m_dTex.descriptorSet                            = makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1468         m_dTex.inImageDescriptorInfo            = makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1469         m_dTex.outImageDescriptorInfo           = makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1470         m_dTex.computeModule                            = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1471         m_dTex.computePipeline                          = makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1472
1473         DescriptorSetUpdateBuilder()
1474                 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1475                 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1476                 .update(m_vk, m_device);
1477
1478         // Transition images for shader access (texture / imageStore)
1479         const VkImageMemoryBarrier imageBarriers[]      =
1480         {
1481                 {
1482                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1483                         DE_NULL,                                                                                        // const void*                          pNext;
1484                         (VkAccessFlags)m_imageUploadAccessMask,                         // VkAccessFlags                        srcAccessMask;
1485                         (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,                       // VkAccessFlags                        dstAccessMask;
1486                         m_imageLayoutAfterUpload,                                                       // VkImageLayout                        oldLayout;
1487                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,                       // VkImageLayout                        newLayout;
1488                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1489                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1490                         m_image,                                                                                        // VkImage                                      image;
1491                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1492                 },
1493                 {
1494                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1495                         DE_NULL,                                                                                        // const void*                          pNext;
1496                         (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1497                         (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1498                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1499                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        newLayout;
1500                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1501                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1502                         *m_dTex.outImage,                                                                       // VkImage                                      image;
1503                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1504                 }
1505         };
1506
1507         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1508                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1509
1510         // Dispatch
1511         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1512         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1513         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1514
1515         // Copy output image to color buffer
1516         copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1517 }
1518
1519 void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1520 {
1521         // Create output image with download result
1522         const VkImageUsageFlags usageFlags      = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1523         m_dLoad.outImage                                        = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1524         m_dLoad.outImageAlloc                           = bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1525         m_dLoad.outImageView                            = makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1526
1527         const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1528         {
1529                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,     // VkStructureType              sType
1530                 DE_NULL,                                                                                        // const void*                  pNext
1531                 VK_IMAGE_USAGE_STORAGE_BIT,                                                     // VkImageUsageFlags    usage;
1532         };
1533         m_dLoad.inImageView                                     = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1534                                                                                                                 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1535
1536         // Setup compute pipeline
1537         m_dLoad.descriptorPool                          = DescriptorPoolBuilder()
1538                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1539                 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1540
1541         m_dLoad.descriptorSetLayout                     = DescriptorSetLayoutBuilder()
1542                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1543                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1544                 .build(m_vk, m_device);
1545
1546         m_dLoad.pipelineLayout                          = makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1547         m_dLoad.descriptorSet                           = makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1548         m_dLoad.inImageDescriptorInfo           = makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1549         m_dLoad.outImageDescriptorInfo          = makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1550         m_dLoad.computeModule                           = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1551         m_dLoad.computePipeline                         = makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1552
1553         DescriptorSetUpdateBuilder()
1554                 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1555                 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1556                 .update(m_vk, m_device);
1557
1558         // Transition storage images for shader access (imageLoad/Store)
1559         VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1560         const VkImageMemoryBarrier imageBarriers[]      =
1561         {
1562                 {
1563                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1564                         DE_NULL,                                                                                        // const void*                          pNext;
1565                         (VkAccessFlags)m_imageUploadAccessMask,                         // VkAccessFlags                        srcAccessMask;
1566                         (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,                       // VkAccessFlags                        dstAccessMask;
1567                         m_imageLayoutAfterUpload,                                                       // VkImageLayout                        oldLayout;
1568                         requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1569                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1570                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1571                         m_image,                                                                                        // VkImage                                      image;
1572                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1573                 },
1574                 {
1575                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
1576                         DE_NULL,                                                                                        // const void*                          pNext;
1577                         (VkAccessFlags)0,                                                                       // VkAccessFlags                        srcAccessMask;
1578                         (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,                      // VkAccessFlags                        dstAccessMask;
1579                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
1580                         requiredImageLayout,                                                            // VkImageLayout                        newLayout;
1581                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
1582                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
1583                         *m_dLoad.outImage,                                                                      // VkImage                                      image;
1584                         makeColorSubresourceRange(0, m_caseDef.numLayers),      // VkImageSubresourceRange      subresourceRange;
1585                 }
1586         };
1587
1588         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1589                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1590
1591         // Dispatch
1592         m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1593         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1594         m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1595
1596         // Copy output image to color buffer
1597         copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1598 }
1599
1600 void UploadDownloadExecutor::copyImageToBuffer(VkImage                          sourceImage,
1601                                                                                            VkBuffer                             buffer,
1602                                                                                            const IVec3                  size,
1603                                                                                            const VkAccessFlags  srcAccessMask,
1604                                                                                            const VkImageLayout  oldLayout,
1605                                                                                            const deUint32               numLayers)
1606 {
1607         // Copy result to host visible buffer for inspection
1608         const VkImageMemoryBarrier      imageBarrier    =
1609         {
1610                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
1611                 DE_NULL,                                                                        // const void*                          pNext;
1612                 srcAccessMask,                                                          // VkAccessFlags                        srcAccessMask;
1613                 VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
1614                 oldLayout,                                                                      // VkImageLayout                        oldLayout;
1615                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                        newLayout;
1616                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
1617                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
1618                 sourceImage,                                                            // VkImage                                      image;
1619                 makeColorSubresourceRange(0, numLayers)         // VkImageSubresourceRange      subresourceRange;
1620         };
1621
1622         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1623                 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1624
1625         const VkImageSubresourceLayers  subresource     =
1626         {
1627                 VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags    aspectMask;
1628                 0u,                                                                                     // deUint32              mipLevel;
1629                 0u,                                                                                     // deUint32              baseArrayLayer;
1630                 numLayers,                                                                      // deUint32              layerCount;
1631         };
1632
1633         const VkBufferImageCopy                 region          =
1634         {
1635                 0ull,                                                                           // VkDeviceSize                bufferOffset;
1636                 0u,                                                                                     // deUint32                    bufferRowLength;
1637                 0u,                                                                                     // deUint32                    bufferImageHeight;
1638                 subresource,                                                            // VkImageSubresourceLayers    imageSubresource;
1639                 makeOffset3D(0, 0, 0),                                          // VkOffset3D                  imageOffset;
1640                 makeExtent3D(size),                                                     // VkExtent3D                  imageExtent;
1641         };
1642
1643         m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
1644
1645         const VkBufferMemoryBarrier     bufferBarrier =
1646         {
1647                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1648                 DE_NULL,                                                                        // const void*        pNext;
1649                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1650                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1651                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32           srcQueueFamilyIndex;
1652                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32           dstQueueFamilyIndex;
1653                 buffer,                                                                         // VkBuffer           buffer;
1654                 0ull,                                                                           // VkDeviceSize       offset;
1655                 VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1656         };
1657
1658         m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1659                 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1660 }
1661
1662 tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1663 {
1664         const DeviceInterface&                  vk                      = context.getDeviceInterface();
1665         const InstanceInterface&                vki                     = context.getInstanceInterface();
1666         const VkDevice                                  device          = context.getDevice();
1667         const VkPhysicalDevice                  physDevice      = context.getPhysicalDevice();
1668         Allocator&                                              allocator       = context.getDefaultAllocator();
1669
1670         // If this is a VK_KHR_image_format_list test, check that the extension is supported
1671         if (caseDef.isFormatListTest && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_image_format_list"))
1672                 TCU_THROW(NotSupportedError, "VK_KHR_image_format_list not supported");
1673
1674         // Check required features on the format for the required upload/download methods
1675         VkFormatProperties      imageFormatProps, viewFormatProps;
1676         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1677         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1678
1679         VkFormatFeatureFlags    viewFormatFeatureFlags = 0u;
1680         switch (caseDef.upload)
1681         {
1682         case UPLOAD_DRAW:
1683                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1684                 break;
1685         case UPLOAD_STORE:
1686                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1687                 break;
1688         case UPLOAD_CLEAR:
1689                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1690                 break;
1691         case UPLOAD_COPY:
1692                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1693                 break;
1694         default:
1695                 DE_FATAL("Invalid upload method");
1696                 break;
1697         }
1698         switch (caseDef.download)
1699         {
1700         case DOWNLOAD_TEXTURE:
1701                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1702                 // For the texture case we write the samples read to a separate output image with the same view format
1703                 // so we need to check that we can also use the view format for storage
1704                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1705                 break;
1706         case DOWNLOAD_LOAD:
1707                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1708                 break;
1709         case DOWNLOAD_COPY:
1710                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1711                 break;
1712         default:
1713                 DE_FATAL("Invalid download method");
1714                 break;
1715         }
1716
1717         if ((viewFormatFeatureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) &&
1718                 isStorageImageExtendedFormat(caseDef.viewFormat) &&
1719                 !getPhysicalDeviceFeatures(vki, physDevice).shaderStorageImageExtendedFormats)
1720         {
1721                 TCU_THROW(NotSupportedError, "View format requires shaderStorageImageExtended");
1722         }
1723
1724         if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1725                 TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1726
1727         const bool haveMaintenance2 = isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance2");
1728
1729         // We don't use the base image for anything other than transfer
1730         // operations so there are no features to check.  However, The Vulkan
1731         // 1.0 spec does not allow us to create an image view with usage that
1732         // is not supported by the main format.  With VK_KHR_maintenance2, we
1733         // can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1734         if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1735                 !haveMaintenance2)
1736         {
1737                 TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1738         }
1739
1740         // If no format feature flags are supported, the format itself is not supported,
1741         // and images of that format cannot be created.
1742         if (imageFormatProps.optimalTilingFeatures == 0)
1743         {
1744                 TCU_THROW(NotSupportedError, "Base image format is not supported");
1745         }
1746
1747         // Create a color buffer for host-inspection of results
1748         // For the Copy download method, this is the target of the download, for other
1749         // download methods, pixel data will be copied to this buffer from the download
1750         // target
1751         const VkDeviceSize                      colorBufferSize         = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1752         const Unique<VkBuffer>          colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1753         const UniquePtr<Allocation>     colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1754         deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1755         flushAlloc(vk, device, *colorBufferAlloc);
1756
1757         // Execute the test
1758         UploadDownloadExecutor executor(context, caseDef);
1759         executor.run(context, *colorBuffer);
1760
1761         // Verify results
1762         {
1763                 invalidateAlloc(vk, device, *colorBufferAlloc);
1764
1765                 // For verification purposes, we use the format of the upload to generate the expected image
1766                 const VkFormat                                          format                  = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1767                 const tcu::TextureFormat                        tcuFormat               = mapVkFormat(format);
1768                 const bool                                                      isIntegerFormat = isUintFormat(format) || isIntFormat(format);
1769                 const tcu::ConstPixelBufferAccess       resultImage             (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1770                 tcu::TextureLevel                                       textureLevel    (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1771                 const tcu::PixelBufferAccess            expectedImage   = textureLevel.getAccess();
1772                 generateExpectedImage(expectedImage, caseDef);
1773
1774                 bool ok;
1775                 if (isIntegerFormat)
1776                         ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1777                 else
1778                         ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1779                 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1780         }
1781 }
1782
1783 tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1784 {
1785         de::MovePtr<TestCaseGroup> testGroup    (new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1786         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1787         {
1788                 const Texture&                                  texture                                 = s_textures[textureNdx];
1789                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType    (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1790
1791                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1792                 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1793                 {
1794                         if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1795                         {
1796                                 for (int upload = 0; upload < UPLOAD_LAST; upload++)
1797                                 for (int download = 0; download < DOWNLOAD_LAST; download++)
1798                                 {
1799                                         CaseDef caseDef =
1800                                         {
1801                                                 texture.type(),
1802                                                 texture.layerSize(),
1803                                                 static_cast<deUint32>(texture.numLayers()),
1804                                                 s_formats[imageFormatNdx],
1805                                                 s_formats[viewFormatNdx],
1806                                                 static_cast<enum Upload>(upload),
1807                                                 static_cast<enum Download>(download),
1808                                                 false,                          // isFormatListTest;
1809                                                 false,                          // isSwapchainImageTest
1810                                                 vk::wsi::TYPE_LAST      // wsiType
1811                                         };
1812
1813                                         std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1814                                                 "_" + getUploadString(upload) + "_" + getDownloadString(download);
1815                                         addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1816
1817                                         caseDef.isFormatListTest = true;
1818                                         caseName += "_format_list";
1819                                         addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1820                                 }
1821                         }
1822                 }
1823
1824                 testGroup->addChild(groupByImageViewType.release());
1825         }
1826
1827         return testGroup.release();
1828 }
1829
1830 typedef vector<VkExtensionProperties> Extensions;
1831
1832 void checkAllSupported(const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
1833 {
1834         for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
1835                 requiredExtName != requiredExtensions.end();
1836                 ++requiredExtName)
1837         {
1838                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
1839                         TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
1840         }
1841 }
1842
1843 Move<VkInstance> createInstanceWithWsi(const PlatformInterface&         vkp,
1844                                                                            deUint32                                             version,
1845                                                                            const Extensions&                    supportedExtensions,
1846                                                                            Type                                                 wsiType,
1847                                                                            const VkAllocationCallbacks* pAllocator = DE_NULL)
1848 {
1849         vector<string>  extensions;
1850
1851         extensions.push_back("VK_KHR_surface");
1852         extensions.push_back(getExtensionName(wsiType));
1853
1854         // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
1855         // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
1856         // but using them without enabling the extension is not allowed. Thus we have
1857         // two options:
1858         //
1859         // 1) Filter out non-core formats to stay within valid usage.
1860         //
1861         // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
1862         //
1863         // We opt for (2) as it provides basic coverage for the extension as a bonus.
1864         if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
1865                 extensions.push_back("VK_EXT_swapchain_colorspace");
1866
1867         checkAllSupported(supportedExtensions, extensions);
1868
1869         return vk::createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
1870 }
1871
1872
1873 Move<VkDevice> createDeviceWithWsi(const PlatformInterface&             vkp,
1874                                                                    VkInstance                                   instance,
1875                                                                    const InstanceInterface&             vki,
1876                                                                    VkPhysicalDevice                             physicalDevice,
1877                                                                    const Extensions&                    supportedExtensions,
1878                                                                    const deUint32                               queueFamilyIndex,
1879                                                                    const VkAllocationCallbacks* pAllocator = DE_NULL)
1880 {
1881         const float                                             queuePriorities[] = { 1.0f };
1882         const VkDeviceQueueCreateInfo   queueInfos[] =
1883         {
1884                 {
1885                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1886                         DE_NULL,
1887                         (VkDeviceQueueCreateFlags)0,
1888                         queueFamilyIndex,
1889                         DE_LENGTH_OF_ARRAY(queuePriorities),
1890                         &queuePriorities[0]
1891                 }
1892         };
1893         VkPhysicalDeviceFeatures                features;
1894         deMemset(&features, 0x0, sizeof(features));
1895
1896         const char* const                               extensions[] = { "VK_KHR_swapchain", "VK_KHR_swapchain_mutable_format" };
1897         const VkDeviceCreateInfo                deviceParams =
1898         {
1899                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1900                 DE_NULL,
1901                 (VkDeviceCreateFlags)0,
1902                 DE_LENGTH_OF_ARRAY(queueInfos),
1903                 &queueInfos[0],
1904                 0u,                                                                     // enabledLayerCount
1905                 DE_NULL,                                                        // ppEnabledLayerNames
1906                 DE_LENGTH_OF_ARRAY(extensions),         // enabledExtensionCount
1907                 DE_ARRAY_BEGIN(extensions),                     // ppEnabledExtensionNames
1908                 &features
1909         };
1910
1911         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
1912         {
1913                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx])))
1914                         TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
1915         }
1916
1917         return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
1918 }
1919
1920 deUint32 getNumQueueFamilyIndices(const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
1921 {
1922         deUint32        numFamilies = 0;
1923
1924         vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
1925
1926         return numFamilies;
1927 }
1928
1929 vector<deUint32> getSupportedQueueFamilyIndices(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
1930 {
1931         const deUint32          numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
1932         vector<deUint32>        supportedFamilyIndices;
1933
1934         for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
1935         {
1936                 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
1937                         supportedFamilyIndices.push_back(queueFamilyNdx);
1938         }
1939
1940         return supportedFamilyIndices;
1941 }
1942
1943 deUint32 chooseQueueFamilyIndex(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
1944 {
1945         const vector<deUint32>  supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
1946
1947         if (supportedFamilyIndices.empty())
1948                 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
1949
1950         return supportedFamilyIndices[0];
1951 }
1952
1953 struct InstanceHelper
1954 {
1955         const vector<VkExtensionProperties>     supportedExtensions;
1956         const Unique<VkInstance>                        instance;
1957         const InstanceDriver                            vki;
1958
1959         InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
1960                 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
1961                         DE_NULL))
1962                 , instance(createInstanceWithWsi(context.getPlatformInterface(),
1963                         context.getUsedApiVersion(),
1964                         supportedExtensions,
1965                         wsiType,
1966                         pAllocator))
1967                 , vki(context.getPlatformInterface(), *instance)
1968         {}
1969 };
1970
1971
1972 struct DeviceHelper
1973 {
1974         const VkPhysicalDevice  physicalDevice;
1975         const deUint32                  queueFamilyIndex;
1976         const Unique<VkDevice>  device;
1977         const DeviceDriver              vkd;
1978         const VkQueue                   queue;
1979
1980         DeviceHelper(Context&                                           context,
1981                 const InstanceInterface&                vki,
1982                 VkInstance                                      instance,
1983                 VkSurfaceKHR                                    surface,
1984                 const VkAllocationCallbacks*    pAllocator = DE_NULL)
1985                 : physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
1986                 , queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
1987                 , device(createDeviceWithWsi(context.getPlatformInterface(),
1988                         context.getInstance(),
1989                         vki,
1990                         physicalDevice,
1991                         enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
1992                         queueFamilyIndex,
1993                         pAllocator))
1994                 , vkd(context.getPlatformInterface(), context.getInstance(), *device)
1995                 , queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
1996         {
1997         }
1998 };
1999
2000 MovePtr<Display> createDisplay(const vk::Platform&      platform,
2001         const Extensions&       supportedExtensions,
2002         Type                            wsiType)
2003 {
2004         try
2005         {
2006                 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
2007         }
2008         catch (const tcu::NotSupportedError& e)
2009         {
2010                 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
2011                 {
2012                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
2013                         // must support creating native display & window for that WSI type.
2014                         throw tcu::TestError(e.getMessage());
2015                 }
2016                 else
2017                         throw;
2018         }
2019 }
2020
2021 MovePtr<Window> createWindow(const Display& display, const Maybe<UVec2>& initialSize)
2022 {
2023         try
2024         {
2025                 return MovePtr<Window>(display.createWindow(initialSize));
2026         }
2027         catch (const tcu::NotSupportedError& e)
2028         {
2029                 // See createDisplay - assuming that wsi::Display was supported platform port
2030                 // should also support creating a window.
2031                 throw tcu::TestError(e.getMessage());
2032         }
2033 }
2034
2035 struct NativeObjects
2036 {
2037         const UniquePtr<Display>        display;
2038         const UniquePtr<Window>         window;
2039
2040         NativeObjects(Context&                          context,
2041                 const Extensions&       supportedExtensions,
2042                 Type                                    wsiType,
2043                 const Maybe<UVec2>&     initialWindowSize = tcu::nothing<UVec2>())
2044                 : display(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
2045                 , window(createWindow(*display, initialWindowSize))
2046         {}
2047 };
2048
2049 Move<VkSwapchainKHR> makeSwapchain(const DeviceInterface&               vk,
2050                                                                         const VkDevice                          device,
2051                                                                         const vk::wsi::Type                     wsiType,
2052                                                                         const VkSurfaceKHR                      surface,
2053                                                                         const VkSurfaceCapabilitiesKHR          capabilities,
2054                                                                         const VkSurfaceFormatKHR        surfaceFormat,
2055                                                                         const VkFormat                          viewFormat,
2056                                                                         const deUint32                          numLayers,
2057                                                                         const VkImageUsageFlags         usage,
2058                                                                         const tcu::UVec2&                       desiredSize,
2059                                                                         deUint32                                        desiredImageCount
2060 )
2061 {
2062         const VkFormat formatList[2] =
2063         {
2064                 surfaceFormat.format,
2065                 viewFormat
2066         };
2067
2068         const VkImageFormatListCreateInfoKHR formatListInfo =
2069         {
2070                 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,    // VkStructureType                      sType;
2071                 DE_NULL,                                                                                                // const void*                          pNext;
2072                 2u,                                                                                                             // deUint32                                     viewFormatCount
2073                 formatList                                                                                              // const VkFormat*                      pViewFormats
2074         };
2075
2076         const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
2077         const PlatformProperties&                       platformProperties = getPlatformProperties(wsiType);
2078
2079         const VkSwapchainCreateInfoKHR          swapchainInfo =
2080         {
2081                 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,            // VkStructureType                                      sType;
2082                 &formatListInfo,                                                                        // const void*                                          pNext;
2083                 VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR,                     // VkSwapchainCreateFlagsKHR            flags;
2084                 surface,                                                                                        // VkSurfaceKHR                                         surface;
2085                 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount), // deUint32                                             minImageCount;
2086                 surfaceFormat.format,                                                           // VkFormat                                                     imageFormat;
2087                 surfaceFormat.colorSpace,                                                       // VkColorSpaceKHR                                      imageColorSpace;
2088                 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
2089                 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),     // VkExtent2D                                           imageExtent;
2090                 numLayers,                                                                                      // deUint32                                                     imageArrayLayers;
2091                 usage,                                                                                          // VkImageUsageFlags                            imageUsage;
2092                 VK_SHARING_MODE_EXCLUSIVE,                                                      // VkSharingMode                                        imageSharingMode;
2093                 0u,                                                                                                     // deUint32                                                     queueFamilyIndexCount;
2094                 (const deUint32*)DE_NULL,                                                       // const deUint32*                                      pQueueFamilyIndices;
2095                 transform,                                                                                      // VkSurfaceTransformFlagBitsKHR        preTransform;
2096                 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,                                      // VkCompositeAlphaFlagBitsKHR          compositeAlpha;
2097                 VK_PRESENT_MODE_FIFO_KHR,                                                       // VkPresentModeKHR                                     presentMode;
2098                 VK_FALSE,                                                                                       // VkBool32                                                     clipped;
2099                 (VkSwapchainKHR)0                                                                       // VkSwapchainKHR                                       oldSwapchain;
2100         };
2101
2102         return createSwapchainKHR(vk, device, &swapchainInfo);
2103 }
2104
2105 tcu::TestStatus testSwapchainMutable(Context& context, CaseDef caseDef)
2106 {
2107         const Type                                              wsiType(caseDef.wsiType);
2108         const tcu::UVec2                                desiredSize(256, 256);
2109         const InstanceHelper                    instHelper(context, wsiType);
2110         const NativeObjects                             native(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
2111         const Unique<VkSurfaceKHR>              surface(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
2112         const DeviceHelper                              devHelper(context, instHelper.vki, *instHelper.instance, *surface);
2113         const DeviceInterface&                  vk = devHelper.vkd;
2114         const InstanceDriver&                   vki = instHelper.vki;
2115         const VkDevice                                  device = *devHelper.device;
2116         const VkPhysicalDevice                  physDevice = devHelper.physicalDevice;
2117
2118         Allocator&                                              allocator = context.getDefaultAllocator();
2119
2120         // Check required features on the format for the required upload/download methods
2121         VkFormatProperties      imageFormatProps, viewFormatProps;
2122         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
2123         vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
2124
2125         const VkImageUsageFlags                         imageUsage = getImageUsageForTestCase(caseDef);
2126
2127         const VkSurfaceCapabilitiesKHR          capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
2128                                                                                                                                                                                         physDevice,
2129                                                                                                                                                                                         *surface);
2130
2131         if (caseDef.numLayers > capabilities.maxImageArrayLayers)
2132                 caseDef.numLayers = capabilities.maxImageArrayLayers;
2133
2134         // Check support for requested formats by swapchain surface
2135         const vector<VkSurfaceFormatKHR>        surfaceFormats = getPhysicalDeviceSurfaceFormats(vki,
2136                                                                                                                                                                                  physDevice,
2137                                                                                                                                                                                  *surface);
2138
2139         const VkSurfaceFormatKHR*                       surfaceFormat = DE_NULL;
2140         const VkFormat*                                         viewFormat = DE_NULL;
2141
2142         for (vector<VkSurfaceFormatKHR>::size_type i = 0; i < surfaceFormats.size(); i++)
2143         {
2144                 if (surfaceFormats[i].format == caseDef.imageFormat)
2145                         surfaceFormat = &surfaceFormats[i];
2146
2147                 if (surfaceFormats[i].format == caseDef.viewFormat)
2148                         viewFormat = &surfaceFormats[i].format;
2149         }
2150
2151         if (surfaceFormat == DE_NULL)
2152                 TCU_THROW(NotSupportedError, "Image format is not supported by swapchain.");
2153
2154         if (viewFormat == DE_NULL)
2155                 TCU_THROW(NotSupportedError, "Image view format is not supported by swapchain.");
2156
2157         if ((capabilities.supportedUsageFlags & imageUsage) != imageUsage)
2158                 TCU_THROW(NotSupportedError, "Image usage request not supported by swapchain.");
2159
2160         const Unique<VkSwapchainKHR>    swapchain(
2161                 makeSwapchain(
2162                         vk,
2163                         device,
2164                         caseDef.wsiType,
2165                         *surface,
2166                         capabilities,
2167                         *surfaceFormat,
2168                         caseDef.viewFormat,
2169                         caseDef.numLayers,
2170                         imageUsage,
2171                         desiredSize,
2172                         2)
2173                 );
2174         const vector<VkImage>                   swapchainImages = getSwapchainImages(vk, device, *swapchain);
2175
2176         VkFormatFeatureFlags                    viewFormatFeatureFlags = 0u;
2177         switch (caseDef.upload)
2178         {
2179         case UPLOAD_DRAW:
2180                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2181                 break;
2182         case UPLOAD_STORE:
2183                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2184                 break;
2185         default:
2186                 DE_FATAL("Invalid upload method");
2187                 break;
2188         }
2189         switch (caseDef.download)
2190         {
2191         case DOWNLOAD_TEXTURE:
2192                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
2193                 // For the texture case we write the samples read to a separate output image with the same view format
2194                 // so we need to check that we can also use the view format for storage
2195                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2196                 break;
2197         case DOWNLOAD_LOAD:
2198                 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2199                 break;
2200         default:
2201                 DE_FATAL("Invalid download method");
2202                 break;
2203         }
2204
2205         if ((viewFormatFeatureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) &&
2206                 isStorageImageExtendedFormat(caseDef.viewFormat) &&
2207                 !getPhysicalDeviceFeatures(vki, physDevice).shaderStorageImageExtendedFormats)
2208         {
2209                 TCU_THROW(NotSupportedError, "View format requires shaderStorageImageExtended");
2210         }
2211
2212         if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
2213                 TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
2214
2215         // We don't use the base image for anything other than transfer
2216         // operations so there are no features to check.  However, The Vulkan
2217         // 1.0 spec does not allow us to create an image view with usage that
2218         // is not supported by the main format.  With VK_KHR_maintenance2, we
2219         // can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
2220         if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
2221                 !isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance2"))
2222         {
2223                 TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
2224         }
2225
2226         // Create a color buffer for host-inspection of results
2227         // For the Copy download method, this is the target of the download, for other
2228         // download methods, pixel data will be copied to this buffer from the download
2229         // target
2230         const VkDeviceSize                      colorBufferSize = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
2231         const Unique<VkBuffer>          colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2232         const UniquePtr<Allocation>     colorBufferAlloc(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
2233         deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
2234         flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
2235
2236
2237         // Execute the test
2238         UploadDownloadExecutor executor(context, caseDef);
2239
2240         executor.runSwapchain(context, *colorBuffer, swapchainImages[0]);
2241
2242         // Verify results
2243         {
2244                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
2245
2246                 // For verification purposes, we use the format of the upload to generate the expected image
2247                 const VkFormat                                          format = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
2248                 const tcu::TextureFormat                        tcuFormat = mapVkFormat(format);
2249                 const bool                                                      isIntegerFormat = isUintFormat(format) || isIntFormat(format);
2250                 const tcu::ConstPixelBufferAccess       resultImage(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
2251                 tcu::TextureLevel                                       textureLevel(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
2252                 const tcu::PixelBufferAccess            expectedImage = textureLevel.getAccess();
2253                 generateExpectedImage(expectedImage, caseDef);
2254
2255                 bool ok;
2256                 if (isIntegerFormat)
2257                         ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
2258                 else
2259                         ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
2260                 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
2261         }
2262 }
2263
2264 tcu::TestCaseGroup* createSwapchainImageMutableTests(TestContext& testCtx)
2265 {
2266         de::MovePtr<TestCaseGroup> testGroup(new TestCaseGroup(testCtx, "swapchain_mutable", "Cases with swapchain mutable images"));
2267
2268         for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
2269         {
2270                 const vk::wsi::Type     wsiType = (vk::wsi::Type)typeNdx;
2271
2272                 de::MovePtr<TestCaseGroup> testGroupWsi(new TestCaseGroup(testCtx, getName(wsiType), ""));
2273
2274                 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2275                 {
2276                         const Texture&                                  texture = s_textures[textureNdx];
2277                         de::MovePtr<tcu::TestCaseGroup> groupByImageViewType(new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2278
2279                         for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++imageFormatNdx)
2280                                 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++viewFormatNdx)
2281                                 {
2282                                         if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_swapchainFormats[imageFormatNdx], s_swapchainFormats[viewFormatNdx]))
2283                                         {
2284                                                 for (int upload = 0; upload < UPLOAD_LAST; upload++)
2285                                                         for (int download = 0; download < DOWNLOAD_LAST; download++)
2286                                                         {
2287                                                                 CaseDef caseDef =
2288                                                                 {
2289                                                                         texture.type(),
2290                                                                         texture.layerSize(),
2291                                                                         static_cast<deUint32>(texture.numLayers()),
2292                                                                         s_swapchainFormats[imageFormatNdx],
2293                                                                         s_swapchainFormats[viewFormatNdx],
2294                                                                         static_cast<enum Upload>(upload),
2295                                                                         static_cast<enum Download>(download),
2296                                                                         true,           // isFormatListTest;
2297                                                                         true,           // isSwapchainImageTest
2298                                                                         wsiType
2299                                                                 };
2300
2301                                                                 std::string caseName = getFormatShortString(s_swapchainFormats[imageFormatNdx]) + "_" + getFormatShortString(s_swapchainFormats[viewFormatNdx]) +
2302                                                                         "_" + getUploadString(upload) + "_" + getDownloadString(download) + "_format_list";
2303
2304                                                                 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testSwapchainMutable, caseDef);
2305                                                         }
2306                                         }
2307                                 }
2308
2309                         testGroupWsi->addChild(groupByImageViewType.release());
2310                 }
2311
2312                 testGroup->addChild(testGroupWsi.release());
2313         }
2314         return testGroup.release();
2315 }
2316
2317 } // image
2318 } // vkt