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