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