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