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