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