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