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 VkImageFormatProperties properties;
1060 if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(),
1061 m_caseDef.imageFormat,
1062 getImageType(m_caseDef.imageType),
1063 VK_IMAGE_TILING_OPTIMAL,
1064 imageUsage,
1065 imageFlags,
1066 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
1067 {
1068 TCU_THROW(NotSupportedError, "Format not supported");
1069 }
1070
1071 m_imageHolder = makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.viewFormat,
1072 m_caseDef.isFormatListTest, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1073 m_image = *m_imageHolder;
1074 m_imageAlloc = bindImage(m_vk, m_device, m_allocator, m_image, MemoryRequirement::Any);
1075
1076 switch (m_caseDef.upload)
1077 {
1078 case UPLOAD_DRAW:
1079 uploadDraw(context);
1080 break;
1081 case UPLOAD_STORE:
1082 uploadStore(context);
1083 break;
1084 case UPLOAD_CLEAR:
1085 uploadClear(context);
1086 break;
1087 case UPLOAD_COPY:
1088 uploadCopy(context);
1089 break;
1090 default:
1091 DE_FATAL("Unsupported upload method");
1092 }
1093
1094 switch (m_caseDef.download)
1095 {
1096 case DOWNLOAD_COPY:
1097 downloadCopy(context, buffer);
1098 break;
1099 case DOWNLOAD_LOAD:
1100 downloadLoad(context, buffer);
1101 break;
1102 case DOWNLOAD_TEXTURE:
1103 downloadTexture(context, buffer);
1104 break;
1105 default:
1106 DE_FATAL("Unsupported download method");
1107 }
1108
1109 endCommandBuffer(m_vk, *m_cmdBuffer);
1110 submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1111 }
1112
uploadClear(Context & context)1113 void UploadDownloadExecutor::uploadClear(Context& context)
1114 {
1115 (void) context;
1116
1117 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1118
1119 const VkImageSubresourceRange subresourceRange = makeColorSubresourceRange(0, m_caseDef.numLayers);
1120 const VkImageMemoryBarrier imageInitBarrier =
1121 {
1122 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1123 DE_NULL, // const void* pNext;
1124 0u, // VkAccessFlags srcAccessMask;
1125 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAcessMask;
1126 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1127 requiredImageLayout, // VkImageLayout newLayout;
1128 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1129 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1130 m_image, // VkImage image;
1131 subresourceRange // VkImageSubresourceRange subresourceRange;
1132 };
1133
1134 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1135 0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1136
1137 for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1138 {
1139 const VkImageSubresourceRange layerSubresourceRange = makeColorSubresourceRange(layer, 1u);
1140 const deUint32 colorIdx = layer % COLOR_TABLE_SIZE;
1141 const VkClearColorValue clearColor = m_imageIsIntegerFormat ? getClearValueInt(m_caseDef, colorIdx).color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1142 m_vk.cmdClearColorImage(*m_cmdBuffer, m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1143 }
1144
1145 m_imageLayoutAfterUpload = requiredImageLayout;
1146 m_imageUploadAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1147 }
1148
uploadStore(Context & context)1149 void UploadDownloadExecutor::uploadStore(Context& context)
1150 {
1151 const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1152 {
1153 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1154 DE_NULL, // const void* pNext
1155 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
1156 };
1157 m_uStore.imageView = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1158 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1159
1160 // Setup compute pipeline
1161 m_uStore.descriptorPool = DescriptorPoolBuilder()
1162 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1163 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1164
1165 m_uStore.descriptorSetLayout = DescriptorSetLayoutBuilder()
1166 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1167 .build(m_vk, m_device);
1168
1169 m_uStore.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1170 m_uStore.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1171 m_uStore.imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1172 m_uStore.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1173 m_uStore.computePipeline = makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1174
1175 DescriptorSetUpdateBuilder()
1176 .writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1177 .update(m_vk, m_device);
1178
1179 // Transition storage image for shader access (imageStore)
1180 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1181 const VkImageMemoryBarrier imageBarrier =
1182 {
1183 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1184 DE_NULL, // const void* pNext;
1185 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1186 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1187 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1188 requiredImageLayout, // VkImageLayout newLayout;
1189 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1190 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1191 m_image, // VkImage image;
1192 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1193 };
1194
1195 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1196 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1197
1198 // Dispatch
1199 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1200 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1201 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1202
1203 m_imageLayoutAfterUpload = requiredImageLayout;
1204 m_imageUploadAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1205 }
1206
uploadCopy(Context & context)1207 void UploadDownloadExecutor::uploadCopy(Context& context)
1208 {
1209 (void) context;
1210
1211 // Create a host-mappable buffer with the color data to upload
1212 const VkDeviceSize pixelSize = tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1213 const VkDeviceSize layerSize = m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1214
1215 m_uCopy.colorBufferSize = layerSize * m_caseDef.numLayers;
1216 m_uCopy.colorBuffer = makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1217 m_uCopy.colorBufferAlloc = bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1218
1219 // Fill color buffer
1220 const tcu::TextureFormat tcuFormat = mapVkFormat(m_caseDef.imageFormat);
1221 VkDeviceSize layerOffset = 0ull;
1222 for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1223 {
1224 tcu::PixelBufferAccess imageAccess = tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1225 const deUint32 colorIdx = layer % COLOR_TABLE_SIZE;
1226 if (m_imageIsIntegerFormat)
1227 {
1228 const VkClearValue clearValue = getClearValueInt(m_caseDef, colorIdx);
1229 const IVec4 colorInt (clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
1230
1231 tcu::clear(imageAccess, colorInt);
1232 }
1233 else
1234 tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1235 layerOffset += layerSize;
1236 }
1237
1238 flushAlloc(m_vk, m_device, *(m_uCopy.colorBufferAlloc));
1239
1240 // Prepare buffer and image for copy
1241 const VkBufferMemoryBarrier bufferInitBarrier =
1242 {
1243 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1244 DE_NULL, // const void* pNext;
1245 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1246 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1247 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1248 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1249 *m_uCopy.colorBuffer, // VkBuffer buffer;
1250 0ull, // VkDeviceSize offset;
1251 VK_WHOLE_SIZE, // VkDeviceSize size;
1252 };
1253
1254 const VkImageMemoryBarrier imageInitBarrier =
1255 {
1256 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1257 DE_NULL, // const void* pNext;
1258 0u, // VkAccessFlags srcAccessMask;
1259 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1260 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1261 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1262 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1263 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1264 m_image, // VkImage image;
1265 makeColorSubresourceRange(0, m_caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
1266 };
1267
1268 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1269 0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1270
1271 // Copy buffer to image
1272 const VkImageSubresourceLayers subresource =
1273 {
1274 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1275 0u, // deUint32 mipLevel;
1276 0u, // deUint32 baseArrayLayer;
1277 m_caseDef.numLayers, // deUint32 layerCount;
1278 };
1279
1280 const VkBufferImageCopy region =
1281 {
1282 0ull, // VkDeviceSize bufferOffset;
1283 0u, // deUint32 bufferRowLength;
1284 0u, // deUint32 bufferImageHeight;
1285 subresource, // VkImageSubresourceLayers imageSubresource;
1286 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1287 makeExtent3D(m_caseDef.size), // VkExtent3D imageExtent;
1288 };
1289
1290 m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ®ion);
1291
1292 const VkImageMemoryBarrier imagePostInitBarrier =
1293 {
1294 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1295 DE_NULL, // const void* pNext;
1296 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1297 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1298 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1299 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1300 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1301 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1302 m_image, // VkImage image;
1303 makeColorSubresourceRange(0, m_caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
1304 };
1305
1306 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1307 0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1308
1309 m_imageLayoutAfterUpload = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1310 m_imageUploadAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1311 }
1312
uploadDraw(Context & context)1313 void UploadDownloadExecutor::uploadDraw(Context& context)
1314 {
1315 // Create vertex buffer
1316 {
1317 const vector<Vec4> vertices = genVertexData(m_caseDef);
1318 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(Vec4);
1319
1320 m_uDraw.vertexBuffer = makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1321 m_uDraw.vertexBufferAlloc = bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1322 deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1323 flushAlloc(m_vk, m_device, *(m_uDraw.vertexBufferAlloc));
1324 }
1325
1326 // Create attachments and pipelines for each image layer
1327 m_uDraw.pipelineLayout = makePipelineLayout(m_vk, m_device);
1328 m_uDraw.renderPass = makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1329 m_uDraw.vertexModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1330 m_uDraw.fragmentModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1331
1332 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1333 {
1334 const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1335 {
1336 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1337 DE_NULL, // const void* pNext
1338 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
1339 };
1340 Move<VkImageView> imageView = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1341 makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1342 m_uDraw.attachmentHandles.push_back(*imageView);
1343 m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1344 m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1345 m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1346 }
1347
1348 // Create framebuffer
1349 {
1350 const IVec2 size = m_caseDef.size.swizzle(0, 1);
1351
1352 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()));
1353 }
1354
1355 // Create command buffer
1356 {
1357 {
1358 vector<VkClearValue> clearValues (m_caseDef.numLayers, m_viewIsIntegerFormat ? getClearValueInt(m_caseDef, 0) : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1359
1360 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]);
1361 }
1362
1363 // Render
1364 const VkDeviceSize vertexDataPerDraw = 4 * 2 * sizeof(Vec4);
1365 VkDeviceSize vertexBufferOffset = 0ull;
1366 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1367 {
1368 if (subpassNdx != 0)
1369 m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1370
1371 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1372
1373 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1374 m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1375 vertexBufferOffset += vertexDataPerDraw;
1376 }
1377
1378 endRenderPass(m_vk, *m_cmdBuffer);
1379 }
1380
1381 m_imageLayoutAfterUpload = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1382 m_imageUploadAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1383 }
1384
downloadCopy(Context & context,VkBuffer buffer)1385 void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1386 {
1387 (void) context;
1388
1389 copyImageToBuffer(m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1390 }
1391
downloadTexture(Context & context,VkBuffer buffer)1392 void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1393 {
1394 // Create output image with download result
1395 const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1396 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);
1397 m_dTex.outImageAlloc = bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1398 m_dTex.outImageView = makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1399
1400 const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1401 {
1402 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1403 DE_NULL, // const void* pNext
1404 VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage;
1405 };
1406 m_dTex.inImageView = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1407 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1408 m_dTex.sampler = makeSampler(m_vk, m_device);
1409
1410 // Setup compute pipeline
1411 m_dTex.descriptorPool = DescriptorPoolBuilder()
1412 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1413 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1414 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1415
1416 m_dTex.descriptorSetLayout = DescriptorSetLayoutBuilder()
1417 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1418 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1419 .build(m_vk, m_device);
1420
1421 m_dTex.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1422 m_dTex.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1423 m_dTex.inImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1424 m_dTex.outImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1425 m_dTex.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1426 m_dTex.computePipeline = makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1427
1428 DescriptorSetUpdateBuilder()
1429 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1430 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1431 .update(m_vk, m_device);
1432
1433 // Transition images for shader access (texture / imageStore)
1434 const VkImageMemoryBarrier imageBarriers[] =
1435 {
1436 {
1437 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1438 DE_NULL, // const void* pNext;
1439 (VkAccessFlags)m_imageUploadAccessMask, // VkAccessFlags srcAccessMask;
1440 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1441 m_imageLayoutAfterUpload, // VkImageLayout oldLayout;
1442 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1443 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1444 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1445 m_image, // VkImage image;
1446 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1447 },
1448 {
1449 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1450 DE_NULL, // const void* pNext;
1451 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1452 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1453 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1454 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1455 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1456 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1457 *m_dTex.outImage, // VkImage image;
1458 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1459 }
1460 };
1461
1462 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1463 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1464
1465 // Dispatch
1466 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1467 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1468 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1469
1470 // Copy output image to color buffer
1471 copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1472 }
1473
downloadLoad(Context & context,VkBuffer buffer)1474 void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1475 {
1476 // Create output image with download result
1477 const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1478 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);
1479 m_dLoad.outImageAlloc = bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1480 m_dLoad.outImageView = makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1481
1482 const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1483 {
1484 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1485 DE_NULL, // const void* pNext
1486 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
1487 };
1488 m_dLoad.inImageView = makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1489 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1490
1491 // Setup compute pipeline
1492 m_dLoad.descriptorPool = DescriptorPoolBuilder()
1493 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1494 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1495
1496 m_dLoad.descriptorSetLayout = DescriptorSetLayoutBuilder()
1497 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1498 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1499 .build(m_vk, m_device);
1500
1501 m_dLoad.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1502 m_dLoad.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1503 m_dLoad.inImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1504 m_dLoad.outImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1505 m_dLoad.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1506 m_dLoad.computePipeline = makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1507
1508 DescriptorSetUpdateBuilder()
1509 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1510 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1511 .update(m_vk, m_device);
1512
1513 // Transition storage images for shader access (imageLoad/Store)
1514 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1515 const VkImageMemoryBarrier imageBarriers[] =
1516 {
1517 {
1518 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1519 DE_NULL, // const void* pNext;
1520 (VkAccessFlags)m_imageUploadAccessMask, // VkAccessFlags srcAccessMask;
1521 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1522 m_imageLayoutAfterUpload, // VkImageLayout oldLayout;
1523 requiredImageLayout, // VkImageLayout newLayout;
1524 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1525 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1526 m_image, // VkImage image;
1527 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1528 },
1529 {
1530 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1531 DE_NULL, // const void* pNext;
1532 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1533 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1534 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1535 requiredImageLayout, // VkImageLayout newLayout;
1536 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1537 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1538 *m_dLoad.outImage, // VkImage image;
1539 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1540 }
1541 };
1542
1543 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1544 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1545
1546 // Dispatch
1547 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1548 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1549 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1550
1551 // Copy output image to color buffer
1552 copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1553 }
1554
copyImageToBuffer(VkImage sourceImage,VkBuffer buffer,const IVec3 size,const VkAccessFlags srcAccessMask,const VkImageLayout oldLayout,const deUint32 numLayers)1555 void UploadDownloadExecutor::copyImageToBuffer(VkImage sourceImage,
1556 VkBuffer buffer,
1557 const IVec3 size,
1558 const VkAccessFlags srcAccessMask,
1559 const VkImageLayout oldLayout,
1560 const deUint32 numLayers)
1561 {
1562 // Copy result to host visible buffer for inspection
1563 const VkImageMemoryBarrier imageBarrier =
1564 {
1565 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1566 DE_NULL, // const void* pNext;
1567 srcAccessMask, // VkAccessFlags srcAccessMask;
1568 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1569 oldLayout, // VkImageLayout oldLayout;
1570 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1571 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1572 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1573 sourceImage, // VkImage image;
1574 makeColorSubresourceRange(0, numLayers) // VkImageSubresourceRange subresourceRange;
1575 };
1576
1577 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1578 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1579
1580 const VkImageSubresourceLayers subresource =
1581 {
1582 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1583 0u, // deUint32 mipLevel;
1584 0u, // deUint32 baseArrayLayer;
1585 numLayers, // deUint32 layerCount;
1586 };
1587
1588 const VkBufferImageCopy region =
1589 {
1590 0ull, // VkDeviceSize bufferOffset;
1591 0u, // deUint32 bufferRowLength;
1592 0u, // deUint32 bufferImageHeight;
1593 subresource, // VkImageSubresourceLayers imageSubresource;
1594 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1595 makeExtent3D(size), // VkExtent3D imageExtent;
1596 };
1597
1598 m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ®ion);
1599
1600 const VkBufferMemoryBarrier bufferBarrier =
1601 {
1602 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1603 DE_NULL, // const void* pNext;
1604 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1605 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1606 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1607 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1608 buffer, // VkBuffer buffer;
1609 0ull, // VkDeviceSize offset;
1610 VK_WHOLE_SIZE, // VkDeviceSize size;
1611 };
1612
1613 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1614 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1615 }
1616
testMutable(Context & context,const CaseDef caseDef)1617 tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1618 {
1619 const DeviceInterface& vk = context.getDeviceInterface();
1620 const VkDevice device = context.getDevice();
1621 Allocator& allocator = context.getDefaultAllocator();
1622
1623 // Create a color buffer for host-inspection of results
1624 // For the Copy download method, this is the target of the download, for other
1625 // download methods, pixel data will be copied to this buffer from the download
1626 // target
1627 const VkDeviceSize colorBufferSize = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1628 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1629 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1630 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1631 flushAlloc(vk, device, *colorBufferAlloc);
1632
1633 // Execute the test
1634 UploadDownloadExecutor executor(context, device, context.getUniversalQueue(), context.getUniversalQueueFamilyIndex(), caseDef);
1635 executor.run(context, *colorBuffer);
1636
1637 // Verify results
1638 {
1639 invalidateAlloc(vk, device, *colorBufferAlloc);
1640
1641 // For verification purposes, we use the format of the upload to generate the expected image
1642 const VkFormat format = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1643 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
1644 const bool isIntegerFormat = isUintFormat(format) || isIntFormat(format);
1645 const tcu::ConstPixelBufferAccess resultImage (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1646 tcu::TextureLevel textureLevel (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1647 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1648 generateExpectedImage(expectedImage, caseDef);
1649
1650 bool ok;
1651 if (isIntegerFormat)
1652 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1653 else
1654 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1655 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1656 }
1657 }
1658
checkSupport(Context & context,const CaseDef caseDef)1659 void checkSupport (Context& context, const CaseDef caseDef)
1660 {
1661 const InstanceInterface& vki = context.getInstanceInterface();
1662 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1663
1664 // If this is a VK_KHR_image_format_list test, check that the extension is supported
1665 if (caseDef.isFormatListTest)
1666 context.requireDeviceFunctionality("VK_KHR_image_format_list");
1667
1668 // Check required features on the format for the required upload/download methods
1669 VkFormatProperties imageFormatProps, viewFormatProps;
1670 vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1671 vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1672
1673 VkFormatFeatureFlags viewFormatFeatureFlags = 0u;
1674 switch (caseDef.upload)
1675 {
1676 case UPLOAD_DRAW:
1677 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1678 break;
1679 case UPLOAD_STORE:
1680 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1681 break;
1682 case UPLOAD_CLEAR:
1683 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1684 break;
1685 case UPLOAD_COPY:
1686 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1687 break;
1688 default:
1689 DE_FATAL("Invalid upload method");
1690 break;
1691 }
1692 switch (caseDef.download)
1693 {
1694 case DOWNLOAD_TEXTURE:
1695 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1696 // For the texture case we write the samples read to a separate output image with the same view format
1697 // so we need to check that we can also use the view format for storage
1698 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1699 break;
1700 case DOWNLOAD_LOAD:
1701 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1702 break;
1703 case DOWNLOAD_COPY:
1704 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1705 break;
1706 default:
1707 DE_FATAL("Invalid download method");
1708 break;
1709 }
1710
1711 if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1712 TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1713
1714 const bool haveMaintenance2 = context.isDeviceFunctionalitySupported("VK_KHR_maintenance2");
1715
1716 // We don't use the base image for anything other than transfer
1717 // operations so there are no features to check. However, The Vulkan
1718 // 1.0 spec does not allow us to create an image view with usage that
1719 // is not supported by the main format. With VK_KHR_maintenance2, we
1720 // can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1721 if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1722 !haveMaintenance2)
1723 {
1724 TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1725 }
1726
1727 // If no format feature flags are supported, the format itself is not supported,
1728 // and images of that format cannot be created.
1729 if (imageFormatProps.optimalTilingFeatures == 0)
1730 {
1731 TCU_THROW(NotSupportedError, "Base image format is not supported");
1732 }
1733 }
1734
createImageMutableTests(TestContext & testCtx)1735 tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1736 {
1737 de::MovePtr<TestCaseGroup> testGroup (new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1738 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1739 {
1740 const Texture& texture = s_textures[textureNdx];
1741 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1742
1743 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1744 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1745 {
1746 if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1747 {
1748 for (int upload = 0; upload < UPLOAD_LAST; upload++)
1749 {
1750 if (upload == UPLOAD_STORE && !isFormatImageLoadStoreCapable(s_formats[viewFormatNdx]))
1751 continue;
1752
1753 for (int download = 0; download < DOWNLOAD_LAST; download++)
1754 {
1755 if ((download == DOWNLOAD_LOAD || download == DOWNLOAD_TEXTURE) &&
1756 !isFormatImageLoadStoreCapable(s_formats[viewFormatNdx]))
1757 continue;
1758
1759 CaseDef caseDef =
1760 {
1761 texture.type(),
1762 texture.layerSize(),
1763 static_cast<deUint32>(texture.numLayers()),
1764 s_formats[imageFormatNdx],
1765 s_formats[viewFormatNdx],
1766 static_cast<enum Upload>(upload),
1767 static_cast<enum Download>(download),
1768 false, // isFormatListTest;
1769 false, // isSwapchainImageTest
1770 vk::wsi::TYPE_LAST // wsiType
1771 };
1772
1773 std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1774 "_" + getUploadString(upload) + "_" + getDownloadString(download);
1775 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testMutable, caseDef);
1776
1777 caseDef.isFormatListTest = true;
1778 caseName += "_format_list";
1779 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testMutable, caseDef);
1780 }
1781 }
1782 }
1783 }
1784
1785 testGroup->addChild(groupByImageViewType.release());
1786 }
1787
1788 return testGroup.release();
1789 }
1790
1791 typedef vector<VkExtensionProperties> Extensions;
1792
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)1793 void checkAllSupported(const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
1794 {
1795 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
1796 requiredExtName != requiredExtensions.end();
1797 ++requiredExtName)
1798 {
1799 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
1800 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
1801 }
1802 }
1803
createInstanceWithWsi(Context & context,const Extensions & supportedExtensions,Type wsiType,const VkAllocationCallbacks * pAllocator=DE_NULL)1804 CustomInstance createInstanceWithWsi(Context& context,
1805 const Extensions& supportedExtensions,
1806 Type wsiType,
1807 const VkAllocationCallbacks* pAllocator = DE_NULL)
1808 {
1809 vector<string> extensions;
1810
1811 extensions.push_back("VK_KHR_surface");
1812 extensions.push_back(getExtensionName(wsiType));
1813
1814 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
1815 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
1816 // but using them without enabling the extension is not allowed. Thus we have
1817 // two options:
1818 //
1819 // 1) Filter out non-core formats to stay within valid usage.
1820 //
1821 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
1822 //
1823 // We opt for (2) as it provides basic coverage for the extension as a bonus.
1824 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
1825 extensions.push_back("VK_EXT_swapchain_colorspace");
1826
1827 checkAllSupported(supportedExtensions, extensions);
1828
1829 return createCustomInstanceWithExtensions(context, extensions, pAllocator);
1830 }
1831
1832
createDeviceWithWsi(const PlatformInterface & vkp,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,const VkAllocationCallbacks * pAllocator,bool enableValidation)1833 Move<VkDevice> createDeviceWithWsi(const PlatformInterface& vkp,
1834 VkInstance instance,
1835 const InstanceInterface& vki,
1836 VkPhysicalDevice physicalDevice,
1837 const Extensions& supportedExtensions,
1838 const deUint32 queueFamilyIndex,
1839 const VkAllocationCallbacks* pAllocator,
1840 bool enableValidation)
1841 {
1842 const float queuePriorities[] = { 1.0f };
1843 const VkDeviceQueueCreateInfo queueInfos[] =
1844 {
1845 {
1846 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1847 DE_NULL,
1848 (VkDeviceQueueCreateFlags)0,
1849 queueFamilyIndex,
1850 DE_LENGTH_OF_ARRAY(queuePriorities),
1851 &queuePriorities[0]
1852 }
1853 };
1854 VkPhysicalDeviceFeatures features;
1855 deMemset(&features, 0x0, sizeof(features));
1856
1857 const char* const extensions[] = { "VK_KHR_swapchain", "VK_KHR_swapchain_mutable_format" };
1858
1859 const VkDeviceCreateInfo deviceParams =
1860 {
1861 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1862 DE_NULL,
1863 (VkDeviceCreateFlags)0,
1864 DE_LENGTH_OF_ARRAY(queueInfos),
1865 &queueInfos[0],
1866 0u, // enabledLayerCount
1867 DE_NULL, // ppEnabledLayerNames
1868 DE_LENGTH_OF_ARRAY(extensions), // enabledExtensionCount
1869 DE_ARRAY_BEGIN(extensions), // ppEnabledExtensionNames
1870 &features
1871 };
1872
1873 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
1874 {
1875 if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx])))
1876 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
1877 }
1878
1879 return createCustomDevice(enableValidation, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
1880 }
1881
1882 struct InstanceHelper
1883 {
1884 const vector<VkExtensionProperties> supportedExtensions;
1885 const CustomInstance instance;
1886 const InstanceDriver& vki;
1887
InstanceHelpervkt::image::InstanceHelper1888 InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
1889 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
1890 DE_NULL))
1891 , instance(createInstanceWithWsi(context,
1892 supportedExtensions,
1893 wsiType,
1894 pAllocator))
1895 , vki(instance.getDriver())
1896 {}
1897 };
1898
1899
1900 struct DeviceHelper
1901 {
1902 const VkPhysicalDevice physicalDevice;
1903 const deUint32 queueFamilyIndex;
1904 const Unique<VkDevice> device;
1905 const DeviceDriver vkd;
1906 const VkQueue queue;
1907
DeviceHelpervkt::image::DeviceHelper1908 DeviceHelper(Context& context,
1909 const InstanceInterface& vki,
1910 VkInstance instance,
1911 VkSurfaceKHR surface,
1912 const VkAllocationCallbacks* pAllocator = DE_NULL)
1913 : physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
1914 , queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
1915 , device(createDeviceWithWsi(context.getPlatformInterface(),
1916 context.getInstance(),
1917 vki,
1918 physicalDevice,
1919 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
1920 queueFamilyIndex,
1921 pAllocator,
1922 context.getTestContext().getCommandLine().isValidationEnabled()))
1923 , vkd(context.getPlatformInterface(), context.getInstance(), *device)
1924 , queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
1925 {
1926 }
1927 };
1928
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,Type wsiType)1929 MovePtr<Display> createDisplay(const vk::Platform& platform,
1930 const Extensions& supportedExtensions,
1931 Type wsiType)
1932 {
1933 try
1934 {
1935 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
1936 }
1937 catch (const tcu::NotSupportedError& e)
1938 {
1939 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
1940 platform.hasDisplay(wsiType))
1941 {
1942 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
1943 // must support creating native display & window for that WSI type.
1944 throw tcu::TestError(e.getMessage());
1945 }
1946 else
1947 throw;
1948 }
1949 }
1950
createWindow(const Display & display,const Maybe<UVec2> & initialSize)1951 MovePtr<Window> createWindow(const Display& display, const Maybe<UVec2>& initialSize)
1952 {
1953 try
1954 {
1955 return MovePtr<Window>(display.createWindow(initialSize));
1956 }
1957 catch (const tcu::NotSupportedError& e)
1958 {
1959 // See createDisplay - assuming that wsi::Display was supported platform port
1960 // should also support creating a window.
1961 throw tcu::TestError(e.getMessage());
1962 }
1963 }
1964
1965 struct NativeObjects
1966 {
1967 const UniquePtr<Display> display;
1968 const UniquePtr<Window> window;
1969
NativeObjectsvkt::image::NativeObjects1970 NativeObjects(Context& context,
1971 const Extensions& supportedExtensions,
1972 Type wsiType,
1973 const Maybe<UVec2>& initialWindowSize = tcu::Nothing)
1974 : display(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
1975 , window(createWindow(*display, initialWindowSize))
1976 {}
1977 };
1978
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)1979 Move<VkSwapchainKHR> makeSwapchain(const DeviceInterface& vk,
1980 const VkDevice device,
1981 const vk::wsi::Type wsiType,
1982 const VkSurfaceKHR surface,
1983 const VkSurfaceCapabilitiesKHR capabilities,
1984 const VkSurfaceFormatKHR surfaceFormat,
1985 const VkFormat viewFormat,
1986 const deUint32 numLayers,
1987 const VkImageUsageFlags usage,
1988 const tcu::UVec2& desiredSize,
1989 deUint32 desiredImageCount
1990 )
1991 {
1992 const VkFormat formatList[2] =
1993 {
1994 surfaceFormat.format,
1995 viewFormat
1996 };
1997
1998 const VkImageFormatListCreateInfo formatListInfo =
1999 {
2000 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR, // VkStructureType sType;
2001 DE_NULL, // const void* pNext;
2002 2u, // deUint32 viewFormatCount
2003 formatList // const VkFormat* pViewFormats
2004 };
2005
2006 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
2007 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
2008
2009 const VkSwapchainCreateInfoKHR swapchainInfo =
2010 {
2011 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType;
2012 &formatListInfo, // const void* pNext;
2013 VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR, // VkSwapchainCreateFlagsKHR flags;
2014 surface, // VkSurfaceKHR surface;
2015 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount), // deUint32 minImageCount;
2016 surfaceFormat.format, // VkFormat imageFormat;
2017 surfaceFormat.colorSpace, // VkColorSpaceKHR imageColorSpace;
2018 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
2019 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())), // VkExtent2D imageExtent;
2020 numLayers, // deUint32 imageArrayLayers;
2021 usage, // VkImageUsageFlags imageUsage;
2022 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode;
2023 0u, // deUint32 queueFamilyIndexCount;
2024 (const deUint32*)DE_NULL, // const deUint32* pQueueFamilyIndices;
2025 transform, // VkSurfaceTransformFlagBitsKHR preTransform;
2026 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha;
2027 VK_PRESENT_MODE_FIFO_KHR, // VkPresentModeKHR presentMode;
2028 VK_FALSE, // VkBool32 clipped;
2029 (VkSwapchainKHR)0 // VkSwapchainKHR oldSwapchain;
2030 };
2031
2032 return createSwapchainKHR(vk, device, &swapchainInfo);
2033 }
2034
testSwapchainMutable(Context & context,CaseDef caseDef)2035 tcu::TestStatus testSwapchainMutable(Context& context, CaseDef caseDef)
2036 {
2037 const Type wsiType(caseDef.wsiType);
2038 const tcu::UVec2 desiredSize(256, 256);
2039 const InstanceHelper instHelper(context, wsiType);
2040 const NativeObjects native(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
2041 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
2042 const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface);
2043 const DeviceInterface& vk = devHelper.vkd;
2044 const InstanceDriver& vki = instHelper.vki;
2045 const VkDevice device = *devHelper.device;
2046 const VkPhysicalDevice physDevice = devHelper.physicalDevice;
2047 SimpleAllocator allocator(vk, device, getPhysicalDeviceMemoryProperties(vki, context.getPhysicalDevice()));
2048
2049 const VkImageUsageFlags imageUsage = getImageUsageForTestCase(caseDef);
2050
2051 {
2052 VkImageFormatProperties properties;
2053 VkResult result;
2054
2055 result = vki.getPhysicalDeviceImageFormatProperties(physDevice, caseDef.imageFormat, getImageType(caseDef.imageType), VK_IMAGE_TILING_OPTIMAL, imageUsage, 0, &properties);
2056
2057 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2058 {
2059 TCU_THROW(NotSupportedError, "Image format is not supported for required usage");
2060 }
2061
2062 result = vki.getPhysicalDeviceImageFormatProperties(physDevice, caseDef.viewFormat, getImageType(caseDef.imageType), VK_IMAGE_TILING_OPTIMAL, imageUsage, 0, &properties);
2063
2064 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2065 {
2066 TCU_THROW(NotSupportedError, "Image view format is not supported for required usage");
2067 }
2068 }
2069
2070 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
2071 physDevice,
2072 *surface);
2073
2074 if (caseDef.numLayers > capabilities.maxImageArrayLayers)
2075 caseDef.numLayers = capabilities.maxImageArrayLayers;
2076
2077 // Check support for requested formats by swapchain surface
2078 const vector<VkSurfaceFormatKHR>surfaceFormats = getPhysicalDeviceSurfaceFormats(vki,
2079 physDevice,
2080 *surface);
2081
2082 const VkSurfaceFormatKHR* surfaceFormat = DE_NULL;
2083 const VkFormat* viewFormat = DE_NULL;
2084
2085 for (vector<VkSurfaceFormatKHR>::size_type i = 0; i < surfaceFormats.size(); i++)
2086 {
2087 if (surfaceFormats[i].format == caseDef.imageFormat)
2088 surfaceFormat = &surfaceFormats[i];
2089
2090 if (surfaceFormats[i].format == caseDef.viewFormat)
2091 viewFormat = &surfaceFormats[i].format;
2092 }
2093
2094 if (surfaceFormat == DE_NULL)
2095 TCU_THROW(NotSupportedError, "Image format is not supported by swapchain.");
2096
2097 if (viewFormat == DE_NULL)
2098 TCU_THROW(NotSupportedError, "Image view format is not supported by swapchain.");
2099
2100 if ((capabilities.supportedUsageFlags & imageUsage) != imageUsage)
2101 TCU_THROW(NotSupportedError, "Image usage request not supported by swapchain.");
2102
2103 const Unique<VkSwapchainKHR> swapchain(
2104 makeSwapchain(
2105 vk,
2106 device,
2107 caseDef.wsiType,
2108 *surface,
2109 capabilities,
2110 *surfaceFormat,
2111 caseDef.viewFormat,
2112 caseDef.numLayers,
2113 imageUsage,
2114 desiredSize,
2115 2)
2116 );
2117 const vector<VkImage> swapchainImages = getSwapchainImages(vk, device, *swapchain);
2118
2119 // Create a color buffer for host-inspection of results
2120 // For the Copy download method, this is the target of the download, for other
2121 // download methods, pixel data will be copied to this buffer from the download
2122 // target
2123 const VkDeviceSize colorBufferSize = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
2124 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2125 const UniquePtr<Allocation> colorBufferAlloc(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
2126 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
2127 flushAlloc(vk, device, *colorBufferAlloc);
2128
2129
2130 // Execute the test
2131 UploadDownloadExecutor executor(context, device, devHelper.queue, devHelper.queueFamilyIndex, caseDef);
2132
2133 executor.runSwapchain(context, *colorBuffer, swapchainImages[0]);
2134
2135 // Verify results
2136 {
2137 invalidateAlloc(vk, device, *colorBufferAlloc);
2138
2139 // For verification purposes, we use the format of the upload to generate the expected image
2140 const VkFormat format = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
2141 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
2142 const bool isIntegerFormat = isUintFormat(format) || isIntFormat(format);
2143 const tcu::ConstPixelBufferAccess resultImage(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
2144 tcu::TextureLevel textureLevel(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
2145 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
2146 generateExpectedImage(expectedImage, caseDef);
2147
2148 bool ok;
2149 if (isIntegerFormat)
2150 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
2151 else
2152 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
2153 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
2154 }
2155 }
2156
createSwapchainImageMutableTests(TestContext & testCtx)2157 tcu::TestCaseGroup* createSwapchainImageMutableTests(TestContext& testCtx)
2158 {
2159 de::MovePtr<TestCaseGroup> testGroup(new TestCaseGroup(testCtx, "swapchain_mutable", "Cases with swapchain mutable images"));
2160
2161 for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
2162 {
2163 const vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
2164
2165 de::MovePtr<TestCaseGroup> testGroupWsi(new TestCaseGroup(testCtx, getName(wsiType), ""));
2166
2167 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2168 {
2169 const Texture& texture = s_textures[textureNdx];
2170 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType(new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2171
2172 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++imageFormatNdx)
2173 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++viewFormatNdx)
2174 {
2175 if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_swapchainFormats[imageFormatNdx], s_swapchainFormats[viewFormatNdx]))
2176 {
2177 for (int upload = 0; upload < UPLOAD_LAST; upload++)
2178 {
2179 if (upload == UPLOAD_STORE && !isFormatImageLoadStoreCapable(s_swapchainFormats[viewFormatNdx]))
2180 continue;
2181
2182 for (int download = 0; download < DOWNLOAD_LAST; download++)
2183 {
2184 if ((download == DOWNLOAD_LOAD || download == DOWNLOAD_TEXTURE) &&
2185 !isFormatImageLoadStoreCapable(s_swapchainFormats[viewFormatNdx]))
2186 continue;
2187
2188 CaseDef caseDef =
2189 {
2190 texture.type(),
2191 texture.layerSize(),
2192 static_cast<deUint32>(texture.numLayers()),
2193 s_swapchainFormats[imageFormatNdx],
2194 s_swapchainFormats[viewFormatNdx],
2195 static_cast<enum Upload>(upload),
2196 static_cast<enum Download>(download),
2197 true, // isFormatListTest;
2198 true, // isSwapchainImageTest
2199 wsiType
2200 };
2201
2202 std::string caseName = getFormatShortString(s_swapchainFormats[imageFormatNdx]) + "_" + getFormatShortString(s_swapchainFormats[viewFormatNdx]) +
2203 "_" + getUploadString(upload) + "_" + getDownloadString(download) + "_format_list";
2204
2205 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testSwapchainMutable, caseDef);
2206 }
2207 }
2208 }
2209 }
2210
2211 testGroupWsi->addChild(groupByImageViewType.release());
2212 }
2213
2214 testGroup->addChild(testGroupWsi.release());
2215 }
2216 return testGroup.release();
2217 }
2218
2219 } // image
2220 } // vkt
2221