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