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