1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22 * \brief Cover for non-zero of memoryTypeBits from vkGetBufferMemoryRequirements*() tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiBufferMemoryRequirementsTests.hpp"
26 #include "vktApiBufferMemoryRequirementsTestsUtils.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 
29 #include "vkMemUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "deFilePath.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuCommandLine.hpp"
37 
38 #include <algorithm>
39 #include <array>
40 #include <functional>
41 #include <iostream>
42 #include <set>
43 #include <sstream>
44 #include <tuple>
45 #include <vector>
46 
47 namespace vkt
48 {
49 namespace api
50 {
51 namespace
52 {
53 
54 using namespace de;
55 using namespace vk;
56 using namespace tcu;
57 
58 struct TestConfig;
59 struct InstanceConfig;
60 
61 enum BufferFateFlagBits
62 {
63     Transfer     = 0x01,
64     Storage      = 0x02,
65     Other        = 0x04,
66     AccStructure = 0x08,
67     Video        = 0x10
68 };
69 typedef uint32_t BufferFateFlags;
70 typedef typename std::add_pointer<typename std::add_const<char>::type>::type cstr;
71 typedef u::BitsSet<BufferFateFlags, BufferFateFlagBits, cstr> BufferFateBits;
72 
73 const BufferFateBits AvailableBufferFateBits{
74     std::make_tuple(Transfer, "transfer_usage_bits"), std::make_tuple(Storage, "storage_usage_bits"),
75     std::make_tuple(Other, "other_usage_bits"),       std::make_tuple(AccStructure, "acc_struct_usage_bits"),
76     std::make_tuple(Video, "video_usage_bits"),
77 };
78 
79 typedef u::BitsSet<VkBufferCreateFlags, VkBufferCreateFlagBits, cstr> BufferCreateBits;
80 typedef u::BitsSet<VkBufferUsageFlags, VkBufferUsageFlagBits, BufferFateFlagBits> BufferUsageBits;
81 typedef u::BitsSet<VkExternalMemoryHandleTypeFlags, VkExternalMemoryHandleTypeFlagBits, cstr, bool>
82     ExternalMemoryHandleBits;
83 typedef SharedPtr<BufferCreateBits> BufferCreateBitsPtr;
84 typedef SharedPtr<BufferUsageBits> BufferUsageBitsPtr;
85 typedef SharedPtr<ExternalMemoryHandleBits> ExternalMemoryHandleBitsPtr;
86 
87 struct TestConfig
88 {
89     bool useMethod2;
90     SharedPtr<BufferCreateBits> createBits;
91     SharedPtr<BufferFateBits> fateBits;
92     bool incExtMemTypeFlags;
93     // Tests the buffer memory size requirement is less than or equal to the aligned size of the buffer.
94     // Requires VK_KHR_maintenance4 extension.
95     bool testSizeRequirements;
96 };
97 struct InstanceConfig
98 {
99     bool useMethod2;
100     SharedPtr<BufferCreateBits> createBits;
101     SharedPtr<BufferFateBits> fateBits;
102     SharedPtr<std::vector<BufferUsageBitsPtr>> usageFlags;
103     bool incExtMemTypeFlags;
104     SharedPtr<std::vector<ExternalMemoryHandleBitsPtr>> extMemHandleFlags;
105     bool testSizeRequirements;
106 
InstanceConfigvkt::api::__anon8ae9a7f70111::InstanceConfig107     InstanceConfig(const TestConfig &conf)
108         : useMethod2(conf.useMethod2)
109         , createBits(conf.createBits)
110         , fateBits(conf.fateBits)
111         , usageFlags(new std::vector<SharedPtr<BufferUsageBits>>)
112         , incExtMemTypeFlags(conf.incExtMemTypeFlags)
113         , extMemHandleFlags(new std::vector<SharedPtr<ExternalMemoryHandleBits>>)
114         , testSizeRequirements(conf.testSizeRequirements)
115     {
116     }
117 };
118 
119 const BufferCreateBits AvailableBufferCreateBits{
120     std::make_tuple(VkBufferCreateFlagBits(0), "no_flags"),
121     std::make_tuple(VK_BUFFER_CREATE_PROTECTED_BIT, "protected"),
122 #ifndef CTS_USES_VULKANSC
123     std::make_tuple(VK_BUFFER_CREATE_SPARSE_BINDING_BIT, "sparse_binding"),
124     std::make_tuple(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, "sparse_residency"),
125     std::make_tuple(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, "sparse_aliased"),
126 #endif // CTS_USES_VULKANSC
127 };
128 
129 const BufferUsageBits AvailableBufferUsageBits{
130     std::make_tuple(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, Transfer),
131     std::make_tuple(VK_BUFFER_USAGE_TRANSFER_DST_BIT, Transfer),
132     std::make_tuple(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, Storage),
133     std::make_tuple(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, Storage),
134     std::make_tuple(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, Storage),
135     std::make_tuple(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, Storage),
136     std::make_tuple(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, Storage),
137     std::make_tuple(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, Storage),
138     std::make_tuple(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, Other),
139     std::make_tuple(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, Other),
140 #ifndef CTS_USES_VULKANSC
141     std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, Video),
142     std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR, Video),
143     std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT, Other),
144     std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, Other),
145     std::make_tuple(VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT, Other),
146     std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, AccStructure),
147     std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, AccStructure),
148     std::make_tuple(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, AccStructure),
149     std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR, Video),
150     std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, Video),
151 #endif // CTS_USES_VULKANSC
152 };
153 
154 #define INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS VkExternalMemoryHandleTypeFlagBits(0)
155 const ExternalMemoryHandleBits AvailableExternalMemoryHandleBits{
156     std::make_tuple(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS, "no_flags", false),
157     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, "opaque_fd", false),
158     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, "opaque_win32", false),
159     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, "opaque_win32_kmt", false),
160     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, "d3d11_tex", false),
161     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, "d3d11_tex_kmt", false),
162     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, "d3d12_heap", false),
163     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, "d3d12_rsrc", false),
164     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, "dma_buf", false),
165 #ifndef CTS_USES_VULKANSC
166     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, "android_hw", false),
167 #endif // CTS_USES_VULKANSC
168     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, "host_alloc", true),
169     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT, "host_mapped", true),
170 #ifndef CTS_USES_VULKANSC
171     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA, "zircon_vmo", false),
172     std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV, "roma_addr", false),
173 #endif // CTS_USES_VULKANSC
174 };
175 
176 template <class Flag, class Bit, class Str, class... Ignored>
bitsToString(const u::BitsSet<Flag,Bit,Str,Ignored...> & bits,const std::string & prefix=std::string ())177 std::string bitsToString(const u::BitsSet<Flag, Bit, Str, Ignored...> &bits, const std::string &prefix = std::string())
178 {
179     DE_ASSERT(!bits.empty());
180     std::stringstream s;
181     s << prefix;
182     bool atLeastOne = false;
183     for (const auto &bit : bits)
184     {
185         if (atLeastOne)
186             s << '_';
187         s << std::get<1>(bit);
188         atLeastOne = true;
189     }
190     return s.str();
191 }
192 
updateBufferCreateFlags(std::vector<BufferCreateBits> & flags)193 void updateBufferCreateFlags(std::vector<BufferCreateBits> &flags)
194 {
195 #ifndef CTS_USES_VULKANSC
196     const auto &residencyBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT);
197     const auto &aliasedBit   = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT);
198     const auto &bindingBit   = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_BINDING_BIT);
199     const auto &protectedBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_PROTECTED_BIT);
200 #endif // CTS_USES_VULKANSC
201     const auto &noneBit = AvailableBufferCreateBits.get(VkBufferCreateFlagBits(0));
202 
203 #ifndef CTS_USES_VULKANSC
204     // VUID-VkBufferCreateInfo-flags-00918 { if sparse residency or sparse aliased include sparse binding }
205     for (auto &bits : flags)
206     {
207         if (bits.contains(residencyBit) || bits.contains(aliasedBit))
208             bits.insert(bindingBit);
209     }
210 
211     // VUID-VkBufferCreateInfo-None-01888 { if sparse residency, sparse aliased or sparse binding then flags must not include protected }
212     const typename BufferCreateBits::key_type disallowdBits[]{residencyBit, aliasedBit, bindingBit};
213     for (auto i = flags.begin(); i != flags.end();)
214     {
215         auto &bits = *i;
216         if (bits.contains(protectedBit))
217         {
218             for (const auto &disallowdBit : disallowdBits)
219             {
220                 auto find = bits.find(disallowdBit);
221                 if (find != bits.end())
222                     bits.erase(find);
223             }
224         }
225         i = bits.empty() ? flags.erase(i) : std::next(i);
226     }
227 #endif // CTS_USES_VULKANSC
228 
229     // since 0 is a valid VkBufferCreateFlagBits flag then remove it flags where it exists along with other non-zero flags
230     for (auto i = flags.begin(); i != flags.end(); ++i)
231     {
232         auto &bits = *i;
233         auto find  = bits.find(noneBit);
234         if (find != bits.end() && bits.size() > 1)
235         {
236             bits.erase(find);
237         }
238     }
239 
240     // remove duplicates
241     for (auto i = flags.begin(); i != flags.end(); ++i)
242     {
243         for (auto j = std::next(i); j != flags.end();)
244             j = (*i == *j) ? flags.erase(j) : std::next(j);
245     }
246 }
247 
248 class BufferMemoryRequirementsInstance : public TestInstance
249 {
250 public:
BufferMemoryRequirementsInstance(Context & context,const InstanceConfig config)251     BufferMemoryRequirementsInstance(Context &context, const InstanceConfig config)
252         : TestInstance(context)
253         , m_config(config)
254     {
255     }
256 
257     virtual ~BufferMemoryRequirementsInstance(void) override = default;
258     virtual tcu::TestStatus iterate(void) override;
259 
260     void getBufferMemoryRequirements(VkMemoryRequirements &result, const DeviceInterface &vkd, VkDevice device,
261                                      VkBuffer buffer) const;
262     void getBufferMemoryRequirements2(VkMemoryRequirements &result, const DeviceInterface &vkd, VkDevice device,
263                                       VkBuffer buffer) const;
264     typedef void (BufferMemoryRequirementsInstance::*Method)(VkMemoryRequirements &result, const DeviceInterface &intf,
265                                                              VkDevice device, VkBuffer buffer) const;
266     template <class T, class... AddArgs>
267     void *chainVkStructure(void *pNext, const AddArgs &...addArgs) const;
268 
269 private:
270     void logFailedSubtests(const std::vector<BufferCreateBitsPtr> &failCreateBits,
271                            const std::vector<BufferUsageBitsPtr> &failUsageBits,
272                            const std::vector<ExternalMemoryHandleBitsPtr> &failExtMemHandleBits) const;
273     const InstanceConfig m_config;
274 };
275 
276 class MemoryRequirementsTest : public TestCase
277 {
278 public:
MemoryRequirementsTest(TestContext & testCtx,const std::string & name,const TestConfig testConfig)279     MemoryRequirementsTest(TestContext &testCtx, const std::string &name, const TestConfig testConfig)
280         : TestCase(testCtx, name)
281         , m_testConfig(testConfig)
282         , m_instConfig(testConfig)
283     {
284     }
285 
286     virtual ~MemoryRequirementsTest(void) override = default;
287     virtual void checkSupport(Context &context) const override;
createInstance(Context & context) const288     virtual TestInstance *createInstance(Context &context) const override
289     {
290         return new BufferMemoryRequirementsInstance(context, m_instConfig);
291     }
292 
293 private:
294     const TestConfig m_testConfig;
295     InstanceConfig m_instConfig;
296 };
297 
298 struct Info
299 {
300     enum Type
301     {
302         Create,
303         Usage
304     } m_type;
305     std::ostringstream m_str;
306     cstr m_file;
307     int m_line;
308     template <class Msg>
Infovkt::api::__anon8ae9a7f70111::Info309     Info(Type type, const Msg &msg, cstr file, int line) : m_type(type)
310                                                          , m_str()
311                                                          , m_file(file)
312                                                          , m_line(line)
313     {
314         m_str << msg;
315     }
operator <<(std::ostringstream & str,const Info & info)316     friend std::ostringstream &operator<<(std::ostringstream &str, const Info &info)
317     {
318         switch (info.m_type)
319         {
320         case Create:
321             str << "Create buffer with " << info.m_str.str() << " not supported by device at "
322                 << de::FilePath(info.m_file).getBaseName() << ":" << info.m_line;
323             break;
324         case Usage:
325             str << info.m_str.str() << " at " << de::FilePath(info.m_file).getBaseName() << ":" << info.m_line;
326             break;
327         }
328         return str;
329     }
330 };
331 #define INFOCREATE(msg_) Info(Info::Create, (msg_), __FILE__, __LINE__)
332 #define INFOUSAGE(msg_) Info(Info::Usage, (msg_), __FILE__, __LINE__)
333 
334 #ifndef CTS_USES_VULKANSC
readVideoCodecOperationFlagsKHR(const InstanceInterface & vki,const VkPhysicalDevice & device)335 VkVideoCodecOperationFlagsKHR readVideoCodecOperationFlagsKHR(const InstanceInterface &vki,
336                                                               const VkPhysicalDevice &device)
337 {
338     uint32_t queueFamilyPropertyCount = 0;
339     vki.getPhysicalDeviceQueueFamilyProperties2(device, &queueFamilyPropertyCount, nullptr);
340     DE_ASSERT(queueFamilyPropertyCount);
341 
342     std::vector<VkQueueFamilyVideoPropertiesKHR> videoQueueFamilyProperties(
343         queueFamilyPropertyCount,
344         {
345             VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR, // VkStructureType                    sType
346             nullptr,                                             // void*                            pNext
347             0 // VkVideoCodecOperationFlagsKHR    videoCodecOperations
348         });
349     std::vector<VkQueueFamilyProperties2> queueFamilyProperties(
350         queueFamilyPropertyCount,
351         {
352             VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, // VkStructureType                    sType
353             nullptr,                                     // void*                            pNext
354             {}                                           // VkQueueFamilyProperties            queueFamilyProperties
355         });
356     for (auto begin = queueFamilyProperties.begin(), i = begin, end = queueFamilyProperties.end(); i != end; ++i)
357     {
358         i->pNext = &videoQueueFamilyProperties.data()[std::distance(begin, i)];
359     }
360 
361     vki.getPhysicalDeviceQueueFamilyProperties2(device, &queueFamilyPropertyCount, queueFamilyProperties.data());
362 
363     VkVideoCodecOperationFlagsKHR codecOperationFlags = VK_VIDEO_CODEC_OPERATION_NONE_KHR;
364     for (const VkQueueFamilyVideoPropertiesKHR &props : videoQueueFamilyProperties)
365     {
366         codecOperationFlags |= props.videoCodecOperations;
367     }
368 
369     return codecOperationFlags;
370 }
371 #endif // CTS_USES_VULKANSC
372 
checkSupport(Context & context) const373 void MemoryRequirementsTest::checkSupport(Context &context) const
374 {
375     const InstanceInterface &intf     = context.getInstanceInterface();
376     const VkPhysicalDevice physDevice = context.getPhysicalDevice();
377     auto &log                         = context.getTestContext().getLog();
378 
379     context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
380 
381     if (m_testConfig.useMethod2)
382         context.requireDeviceFunctionality("VK_KHR_get_memory_requirements2");
383 
384     VkPhysicalDeviceProtectedMemoryFeatures protectedMemFeatures{
385         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, // VkStructureType sType;
386         nullptr,                                                         // void* pNext;
387         VK_FALSE                                                         // VkBool32 protectedMemory;
388     };
389     VkPhysicalDeviceFeatures2 extFeatures{
390         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType sType;
391         &protectedMemFeatures,                            // void* pNext;
392         {}                                                // VkPhysicalDeviceFeatures features;
393     };
394     intf.getPhysicalDeviceFeatures2(physDevice, &extFeatures);
395 
396     const VkPhysicalDeviceFeatures &features   = extFeatures.features;
397     const VkBool32 &protectedMemFeatureEnabled = protectedMemFeatures.protectedMemory;
398 
399     // check the creating bits
400     {
401         std::ostringstream str;
402         bool notSupported      = false;
403         const auto &createBits = *m_testConfig.createBits;
404 
405         if (createBits.contains(VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (VK_FALSE == features.sparseBinding))
406         {
407             str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_BINDING_BIT));
408             notSupported = true;
409         }
410         if (createBits.contains(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (VK_FALSE == features.sparseResidencyBuffer))
411         {
412             if (notSupported)
413                 str << std::endl;
414             str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT));
415             notSupported = true;
416         }
417         if (createBits.contains(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (VK_FALSE == features.sparseResidencyAliased))
418         {
419             if (notSupported)
420                 str << std::endl;
421             str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT));
422             notSupported = true;
423         }
424         if (createBits.contains(VK_BUFFER_CREATE_PROTECTED_BIT) && (VK_FALSE == protectedMemFeatureEnabled))
425         {
426             if (notSupported)
427                 str << std::endl;
428             str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_PROTECTED_BIT));
429             notSupported = true;
430         }
431         if (notSupported)
432         {
433             log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
434             TCU_THROW(NotSupportedError,
435                       "One or more create buffer flags not supported by device (check log for details)");
436         }
437     }
438 
439     // check the usage bits and build instance input
440     {
441         std::vector<BufferUsageBits> usageFlags;
442         for (const auto &bit : *m_testConfig.fateBits)
443         {
444             auto fate = m_testConfig.fateBits->extract(bit);
445             std::vector<VkBufferUsageFlags> usageHints;
446             std::vector<BufferUsageBits> usageFlagsTmp;
447             u::combine(usageFlagsTmp, AvailableBufferUsageBits.select<1>(fate), usageHints);
448             u::mergeFlags(usageFlags, usageFlagsTmp);
449         }
450 
451         std::ostringstream str;
452         std::array<bool, 7> msgs;
453         bool notSupported = false;
454         int entryCount    = 0;
455         msgs.fill(false);
456 
457         for (auto i = usageFlags.begin(); i != usageFlags.end();)
458         {
459             notSupported = false;
460 
461 #ifndef CTS_USES_VULKANSC
462             if (i->any({VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
463                         VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
464                         VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR}) &&
465                 !context.isDeviceFunctionalitySupported("VK_KHR_acceleration_structure"))
466             {
467                 if (!msgs[0])
468                 {
469                     if (entryCount++)
470                         str << std::endl;
471                     str << INFOUSAGE("VK_KHR_acceleration_structure not supported by device");
472                     msgs[0] = true;
473                 }
474                 notSupported = true;
475             }
476 #endif // CTS_USES_VULKANSC
477 
478             if (i->contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) && !context.isBufferDeviceAddressSupported())
479             {
480                 if (!msgs[1])
481                 {
482                     if (entryCount++)
483                         str << std::endl;
484                     str << INFOUSAGE("VK_EXT_buffer_device_address not supported by device");
485                     msgs[1] = true;
486                 }
487                 notSupported = true;
488             }
489 
490 #ifndef CTS_USES_VULKANSC
491             if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR,
492                         VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
493             {
494                 if (!context.isDeviceFunctionalitySupported(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME))
495                 {
496                     if (!msgs[2])
497                     {
498                         if (entryCount++)
499                             str << std::endl;
500                         str << INFOUSAGE("VK_EXT_video_queue not supported by device");
501                         msgs[2] = true;
502                     }
503                     notSupported = true;
504                 }
505                 else
506                 {
507                     const VkVideoCodecOperationFlagsKHR videoFlags = readVideoCodecOperationFlagsKHR(intf, physDevice);
508 
509                     if (i->any({VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
510                     {
511                         if (!context.isDeviceFunctionalitySupported(VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME))
512                         {
513                             if (!msgs[3])
514                             {
515                                 if (entryCount++)
516                                     str << std::endl;
517                                 str << INFOUSAGE("VK_EXT_video_encode_h264 not supported by device");
518                                 msgs[3] = true;
519                             }
520                             notSupported = true;
521                         }
522                         if (!(videoFlags & VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR))
523                         {
524                             if (!msgs[4])
525                             {
526                                 if (entryCount++)
527                                     str << std::endl;
528                                 str << INFOUSAGE("Could not find a queue that supports "
529                                                  "VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT on device");
530                                 msgs[4] = true;
531                             }
532                             notSupported = true;
533                         }
534                     }
535                     if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR}))
536                     {
537                         if (!context.isDeviceFunctionalitySupported(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME))
538                         {
539                             if (!msgs[5])
540                             {
541                                 if (entryCount++)
542                                     str << std::endl;
543                                 str << INFOUSAGE("VK_KHR_video_decode_h264 not supported by device");
544                                 msgs[5] = true;
545                             }
546                             notSupported = true;
547                         }
548                         if (!(videoFlags & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR))
549                         {
550                             if (!msgs[6])
551                             {
552                                 if (entryCount++)
553                                     str << std::endl;
554                                 str << INFOUSAGE("Could not find a queue that supports "
555                                                  "VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR on device");
556                                 msgs[6] = true;
557                             }
558                             notSupported = true;
559                         }
560                     }
561                 }
562             }
563 #endif // CTS_USES_VULKANSC
564 
565             i = notSupported ? usageFlags.erase(i) : std::next(i);
566         }
567 
568         // remove duplicates
569         for (auto i = usageFlags.begin(); i != usageFlags.end(); ++i)
570         {
571             for (auto j = std::next(i); j != usageFlags.end();)
572                 j = (*i == *j) ? usageFlags.erase(j) : std::next(j);
573         }
574 
575         if (usageFlags.empty())
576         {
577             log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
578             TCU_THROW(NotSupportedError,
579                       "One or more buffer usage flags not supported by device (check log for details)");
580         }
581         else
582         {
583             if (entryCount > 0)
584             {
585                 log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
586             }
587             DE_ASSERT(m_instConfig.usageFlags.get());
588             m_instConfig.usageFlags->resize(usageFlags.size());
589             std::transform(usageFlags.begin(), usageFlags.end(), m_instConfig.usageFlags->begin(),
590                            [](BufferUsageBits &bits) { return BufferUsageBits::makeShared(std::move(bits)); });
591         }
592     }
593 
594     // check the external memory handle type bits and build instance input
595     {
596         std::vector<ExternalMemoryHandleBits> extMemHandleFlags;
597         if (m_testConfig.incExtMemTypeFlags)
598             extMemHandleFlags.push_back(
599                 {AvailableExternalMemoryHandleBits.get(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS)});
600         else
601         {
602             std::vector<VkExternalMemoryHandleTypeFlags> handleHints;
603             std::vector<ExternalMemoryHandleBits> handleFlagsTmp;
604             u::combine(handleFlagsTmp, AvailableExternalMemoryHandleBits.select<2>(true), handleHints);
605             u::mergeFlags(extMemHandleFlags, handleFlagsTmp);
606         }
607 
608         DE_ASSERT(m_instConfig.extMemHandleFlags.get());
609         m_instConfig.extMemHandleFlags->resize(extMemHandleFlags.size());
610         std::transform(extMemHandleFlags.begin(), extMemHandleFlags.end(), m_instConfig.extMemHandleFlags->begin(),
611                        [](ExternalMemoryHandleBits &bits)
612                        { return ExternalMemoryHandleBits::makeShared(std::move(bits)); });
613     }
614 
615     if (m_testConfig.testSizeRequirements)
616     {
617         if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance4"))
618             TCU_THROW(NotSupportedError, "VK_KHR_maintenance4 not supported");
619     }
620 }
621 
logFailedSubtests(const std::vector<BufferCreateBitsPtr> & failCreateBits,const std::vector<BufferUsageBitsPtr> & failUsageBits,const std::vector<ExternalMemoryHandleBitsPtr> & failExtMemHandleBits) const622 void BufferMemoryRequirementsInstance::logFailedSubtests(
623     const std::vector<BufferCreateBitsPtr> &failCreateBits, const std::vector<BufferUsageBitsPtr> &failUsageBits,
624     const std::vector<ExternalMemoryHandleBitsPtr> &failExtMemHandleBits) const
625 {
626     const uint32_t flagCount = uint32_t(failCreateBits.size());
627     TestLog &log             = m_context.getTestContext().getLog();
628     uint32_t entries         = 0;
629 
630     DE_ASSERT(flagCount && flagCount == failUsageBits.size() && flagCount == failExtMemHandleBits.size());
631 
632     log << TestLog::Section("Failed", "Failed subtests");
633 
634     for (uint32_t i = 0; i < flagCount; ++i)
635     {
636         {
637             log << TestLog::Section("VkBufferCreateFlags", "Buffer create flags");
638             auto msg = log << TestLog::Message;
639             entries  = 0;
640             for (const auto &createBit : *failCreateBits[i])
641             {
642                 if (entries++)
643                     msg << " ";
644                 const VkBufferCreateFlags flags = BufferCreateBits::extract(createBit);
645                 if (flags == 0)
646                     msg << "0";
647                 else
648                     msg << getBufferCreateFlagsStr(flags);
649             }
650             msg << TestLog::EndMessage << TestLog::EndSection;
651         }
652 
653         {
654             log << TestLog::Section("VkBufferUsageFlags", "Buffer usage flags");
655             auto msg = log << TestLog::Message;
656             entries  = 0;
657             for (const auto &usageBit : *failUsageBits[i])
658             {
659                 if (entries++)
660                     msg << " ";
661                 msg << getBufferUsageFlagsStr(BufferUsageBits::extract(usageBit));
662             }
663             msg << TestLog::EndMessage << TestLog::EndSection;
664         }
665 
666         {
667             log << TestLog::Section("VkExternalMemoryHandleTypeFlags", "External memory handle type flags");
668             auto msg = log << TestLog::Message;
669             entries  = 0;
670             for (const auto &extMemHandleTypeBit : *failExtMemHandleBits[i])
671             {
672                 if (entries++)
673                     msg << " ";
674                 msg << getExternalMemoryHandleTypeFlagsStr(ExternalMemoryHandleBits::extract(extMemHandleTypeBit));
675             }
676             msg << TestLog::EndMessage << TestLog::EndSection;
677         }
678     }
679 
680     log << TestLog::EndSection;
681 }
682 
getBufferMemoryRequirements2(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const683 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements2(VkMemoryRequirements &result,
684                                                                     const DeviceInterface &vkd, VkDevice device,
685                                                                     VkBuffer buffer) const
686 {
687     VkMemoryDedicatedRequirements dedicatedRequirements = {
688         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, // VkStructureType sType;
689         nullptr,                                         // const void* pNext;
690         VK_FALSE,                                        // VkBool32                    prefersDedicatedAllocation
691         VK_FALSE                                         // VkBool32                    requiresDedicatedAllocation
692     };
693 
694     VkMemoryRequirements2 desiredRequirements = {
695         VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType            sType
696         &dedicatedRequirements,                  // void*                    pNext
697         result                                   // VkMemoryRequirements        memoryRequirements
698     };
699 
700     VkBufferMemoryRequirementsInfo2 requirementsInfo = {
701         VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType            sType
702         nullptr,                                             // const void*                pNext
703         buffer                                               // VkBuffer                    buffer
704     };
705 
706     vkd.getBufferMemoryRequirements2(device, &requirementsInfo, &desiredRequirements);
707 
708     result = desiredRequirements.memoryRequirements;
709 }
710 
getBufferMemoryRequirements(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const711 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements(VkMemoryRequirements &result,
712                                                                    const DeviceInterface &vkd, VkDevice device,
713                                                                    VkBuffer buffer) const
714 {
715     vkd.getBufferMemoryRequirements(device, buffer, &result);
716 }
717 
718 template <>
chainVkStructure(void * pNext,const VkExternalMemoryHandleTypeFlags & handleTypes) const719 void *BufferMemoryRequirementsInstance::chainVkStructure<VkExternalMemoryBufferCreateInfo>(
720     void *pNext, const VkExternalMemoryHandleTypeFlags &handleTypes) const
721 {
722     static VkExternalMemoryBufferCreateInfo memInfo{};
723     memInfo.sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
724     memInfo.pNext       = pNext;
725     memInfo.handleTypes = handleTypes;
726 
727     return &memInfo;
728 }
729 
730 #ifndef CTS_USES_VULKANSC
731 template <>
chainVkStructure(void * pNext,const VkBufferUsageFlags & videoCodecUsage) const732 void *BufferMemoryRequirementsInstance::chainVkStructure<VkVideoProfileListInfoKHR>(
733     void *pNext, const VkBufferUsageFlags &videoCodecUsage) const
734 {
735     const bool encode = (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) ||
736                         (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR);
737     const bool decode = (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR) ||
738                         (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR);
739 
740     static VkVideoEncodeH264ProfileInfoKHR encodeProfile{
741         VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR, // VkStructureType sType;
742         nullptr,                                              // const void* pNext;
743         STD_VIDEO_H264_PROFILE_IDC_BASELINE                   // StdVideoH264ProfileIdc stdProfileIdc;
744     };
745 
746     static VkVideoDecodeH264ProfileInfoKHR decodeProfile{
747         VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR, // VkStructureType sType;
748         nullptr,                                              // const void* pNext;
749         STD_VIDEO_H264_PROFILE_IDC_BASELINE,                  // StdVideoH264ProfileIdc stdProfileIdc;
750         VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR   // VkVideoDecodeH264FieldLayoutFlagsEXT fieldLayout;
751     };
752 
753     static const VkVideoProfileInfoKHR videoProfiles[]{
754         // encode profile
755         {
756             VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,       // VkStructureType sType;
757             &encodeProfile,                                 // void* pNext;
758             VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR,   // VkVideoCodecOperationFlagBitsKHR videoCodecOperation;
759             VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR, // VkVideoChromaSubsamplingFlagsKHR chromaSubsampling;
760             VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,         // VkVideoComponentBitDepthFlagsKHR lumaBitDepth;
761             VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR          // VkVideoComponentBitDepthFlagsKHR chromaBitDepth;
762         },
763         // decode profile
764         {
765             VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,       // VkStructureType sType;
766             &decodeProfile,                                 // void* pNext;
767             VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,   // VkVideoCodecOperationFlagBitsKHR videoCodecOperation;
768             VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR, // VkVideoChromaSubsamplingFlagsKHR chromaSubsampling;
769             VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,         // VkVideoComponentBitDepthFlagsKHR lumaBitDepth;
770             VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR          // VkVideoComponentBitDepthFlagsKHR chromaBitDepth;
771         }};
772     static VkVideoProfileListInfoKHR profiles;
773     profiles.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
774     profiles.pNext = pNext;
775     if (encode && decode)
776     {
777         profiles.profileCount = 2u;
778         profiles.pProfiles    = videoProfiles;
779     }
780     else if (encode)
781     {
782         profiles.profileCount = 1u;
783         profiles.pProfiles    = &videoProfiles[0];
784     }
785     else
786     {
787         profiles.profileCount = 1u;
788         profiles.pProfiles    = &videoProfiles[1];
789     }
790     return &profiles;
791 }
792 #endif // CTS_USES_VULKANSC
793 
createProtectedDevice(const Context & context)794 static Move<VkDevice> createProtectedDevice(const Context &context)
795 {
796     auto &cmdLine             = context.getTestContext().getCommandLine();
797     const float queuePriority = 1.0f;
798 
799     VkPhysicalDeviceProtectedMemoryFeatures protectedMemoryFeatures;
800     protectedMemoryFeatures.sType           = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
801     protectedMemoryFeatures.pNext           = DE_NULL;
802     protectedMemoryFeatures.protectedMemory = VK_TRUE;
803 
804     VkDeviceQueueCreateInfo queueInfo = {
805         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
806         DE_NULL,                                    // const void* pNext;
807         vk::VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,   // VkDeviceQueueCreateFlags flags;
808         context.getUniversalQueueFamilyIndex(),     // uint32_t queueFamilyIndex;
809         1u,                                         // uint32_t queueCount;
810         &queuePriority                              // const float* pQueuePriorities;
811     };
812     const VkDeviceCreateInfo deviceInfo = {
813         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
814         &protectedMemoryFeatures,             // const void* pNext;
815         (VkDeviceCreateFlags)0,               // VkDeviceCreateFlags flags;
816         1u,                                   // uint32_t queueCreateInfoCount;
817         &queueInfo,                           // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
818         0u,                                   // uint32_t enabledLayerCount;
819         DE_NULL,                              // const char* const* ppEnabledLayerNames;
820         0u,                                   // uint32_t enabledExtensionCount;
821         DE_NULL,                              // const char* const* ppEnabledExtensionNames;
822         DE_NULL                               // const VkPhysicalDeviceFeatures* pEnabledFeatures;
823     };
824     return createCustomDevice(cmdLine.isValidationEnabled(), context.getPlatformInterface(), context.getInstance(),
825                               context.getInstanceInterface(), context.getPhysicalDevice(), &deviceInfo);
826 }
827 
iterate(void)828 TestStatus BufferMemoryRequirementsInstance::iterate(void)
829 {
830     const DeviceInterface &vkd      = m_context.getDeviceInterface();
831     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
832     const Method method = m_config.useMethod2 ? &BufferMemoryRequirementsInstance::getBufferMemoryRequirements2 :
833                                                 &BufferMemoryRequirementsInstance::getBufferMemoryRequirements;
834 
835     uint32_t passCount = 0;
836     uint32_t failCount = 0;
837     std::vector<BufferCreateBitsPtr> failCreateBits;
838     std::vector<BufferUsageBitsPtr> failUsageBits;
839     std::vector<ExternalMemoryHandleBitsPtr> failExtMemHandleBits;
840 
841     Move<VkDevice> protectedDevice;
842     VkDevice device;
843     if (m_config.createBits->contains(VK_BUFFER_CREATE_PROTECTED_BIT))
844     {
845         protectedDevice = createProtectedDevice(m_context);
846         device          = *protectedDevice;
847     }
848     else
849     {
850         device = m_context.getDevice();
851     }
852 
853     DE_ASSERT(!m_config.createBits->empty());
854     const VkBufferCreateFlags infoCreateFlags = *m_config.createBits;
855     {
856         DE_ASSERT(!m_config.usageFlags->empty());
857         for (auto u = m_config.usageFlags->cbegin(); u != m_config.usageFlags->cend(); ++u)
858         {
859             const VkBufferUsageFlags infoUsageFlags = *(u->get());
860 
861             DE_ASSERT(!m_config.extMemHandleFlags->empty());
862             for (auto m = m_config.extMemHandleFlags->cbegin(); m != m_config.extMemHandleFlags->cend(); ++m)
863             {
864                 const VkExternalMemoryHandleTypeFlags handleFlags = *(m->get());
865 
866                 void *pNext = nullptr;
867 
868 #ifndef CTS_USES_VULKANSC
869                 if (m_config.fateBits->contains(BufferFateFlagBits::Video))
870                 {
871                     pNext = chainVkStructure<VkVideoProfileListInfoKHR>(pNext, infoUsageFlags);
872                 }
873 #endif // CTS_USES_VULKANSC
874                 if (m_config.incExtMemTypeFlags)
875                 {
876                     pNext = chainVkStructure<VkExternalMemoryBufferCreateInfo>(pNext, handleFlags);
877                 }
878                 VkBufferCreateInfo createInfo{
879                     VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
880                     pNext,                                // const void* pNext;
881                     infoCreateFlags,                      // VkBufferCreateFlags flags;
882                     4096u,                                // VkDeviceSize size;
883                     infoUsageFlags,                       // VkBufferUsageFlags usage;
884                     VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
885                     1u,                                   // uint32_t queueFamilyIndexCount;
886                     &queueFamilyIndex,                    // const uint32_t* pQueueFamilyIndices;
887                 };
888 
889 #ifndef CTS_USES_VULKANSC
890                 if (m_config.testSizeRequirements)
891                 {
892                     VkPhysicalDeviceMaintenance4PropertiesKHR maintenance4Properties = {
893                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR, // VkStructureType sType;
894                         DE_NULL,                                                        // void* pNext;
895                         0u                                                              // VkDeviceSize maxBufferSize;
896                     };
897 
898                     VkPhysicalDeviceProperties2 physicalDeviceProperties2 = {
899                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType;
900                         &maintenance4Properties,                        // void* pNext;
901                         {},                                             // VkPhysicalDeviceProperties properties;
902                     };
903 
904                     m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(),
905                                                                                   &physicalDeviceProperties2);
906 
907                     const VkDeviceSize maxBufferSize = maintenance4Properties.maxBufferSize;
908                     DE_ASSERT(maxBufferSize > 0);
909                     VkDeviceSize N = 0;
910 
911                     while ((1ull << N) + 1 < maxBufferSize)
912                     {
913                         createInfo.size = (1ull << N) + 1;
914 
915                         try
916                         {
917                             Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
918 
919                             VkMemoryRequirements reqs{};
920                             (this->*method)(reqs, vkd, device, *buffer);
921 
922                             if (reqs.size <= static_cast<VkDeviceSize>(deAlign64(static_cast<int64_t>(createInfo.size),
923                                                                                  static_cast<int64_t>(reqs.alignment))))
924                             {
925                                 ++passCount;
926                             }
927                             else
928                             {
929                                 ++failCount;
930                                 failCreateBits.emplace_back(m_config.createBits);
931                                 failUsageBits.emplace_back(*u);
932                                 failExtMemHandleBits.emplace_back(*m);
933                             }
934 
935                             N++;
936                         }
937                         catch (const vk::OutOfMemoryError &)
938                         {
939                             break;
940                         }
941                     }
942 
943                     if (m_context.getTestContext().getWatchDog())
944                         qpWatchDog_reset(m_context.getTestContext().getWatchDog());
945                 }
946                 else
947 #endif // CTS_USES_VULKANSC
948                 {
949                     Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
950 
951                     VkMemoryRequirements reqs{};
952                     (this->*method)(reqs, vkd, device, *buffer);
953                     if (reqs.memoryTypeBits)
954                         ++passCount;
955                     else
956                     {
957                         ++failCount;
958                         failCreateBits.emplace_back(m_config.createBits);
959                         failUsageBits.emplace_back(*u);
960                         failExtMemHandleBits.emplace_back(*m);
961                     }
962                 }
963             }
964         }
965     }
966 
967     if (failCount)
968     {
969         logFailedSubtests(failCreateBits, failUsageBits, failExtMemHandleBits);
970         return TestStatus::fail(std::to_string(failCount));
971     }
972 
973     return TestStatus::pass(std::to_string(passCount));
974 }
975 
976 } // unnamed namespace
977 
createBufferMemoryRequirementsTests(tcu::TestContext & testCtx)978 tcu::TestCaseGroup *createBufferMemoryRequirementsTests(tcu::TestContext &testCtx)
979 {
980     struct
981     {
982         bool include;
983         cstr name;
984     } const extMemTypeFlags[]{{false, "ext_mem_flags_excluded"}, {true, "ext_mem_flags_included"}};
985 
986     struct
987     {
988         bool method;
989         cstr name;
990     } const methods[]{{false, "method1"}, {true, "method2"}};
991 
992     std::vector<SharedPtr<BufferCreateBits>> createBitPtrs;
993     {
994         std::vector<VkBufferCreateFlags> hints;
995         std::vector<BufferCreateBits> createFlags;
996         u::combine(createFlags, AvailableBufferCreateBits, hints);
997         updateBufferCreateFlags(createFlags);
998         createBitPtrs.resize(createFlags.size());
999         std::transform(createFlags.begin(), createFlags.end(), createBitPtrs.begin(),
1000                        [](BufferCreateBits &bits) { return BufferCreateBits::makeShared(std::move(bits)); });
1001     }
1002 
1003     std::vector<SharedPtr<BufferFateBits>> fateBitPtrs;
1004     {
1005         // An excerpt above has been disabled consciously for the sake of computational complexity.
1006         // Enabled block does the same things sequentially, it doesn't create cartesian product of combination of bits.
1007 #if 0
1008         std::vector<BufferFateFlags>    hints;
1009         std::vector<BufferFateBits>        bufferFateFlags;
1010         u::combine(bufferFateFlags, AvailableBufferFateBits, hints);
1011         fateBitPtrs.resize(bufferFateFlags.size());
1012         std::transform(bufferFateFlags.begin(), bufferFateFlags.end(), fateBitPtrs.begin(),
1013                        [](BufferFateBits& bits) { return BufferFateBits::makeShared(std::move(bits)); });
1014 #else
1015         fateBitPtrs.resize(AvailableBufferFateBits.size());
1016         std::transform(AvailableBufferFateBits.begin(), AvailableBufferFateBits.end(), fateBitPtrs.begin(),
1017                        [](const typename BufferFateBits::value_type &bit) { return BufferFateBits::makeShared(bit); });
1018 #endif
1019     }
1020 
1021     auto groupRoot = new TestCaseGroup(testCtx, "buffer_memory_requirements");
1022     for (const auto &createBits : createBitPtrs)
1023     {
1024         auto groupCreate = new TestCaseGroup(testCtx, bitsToString(*createBits, "create_").c_str());
1025         for (const auto &extMemTypeFlag : extMemTypeFlags)
1026         {
1027             auto groupExtMemTypeFlags = new TestCaseGroup(testCtx, extMemTypeFlag.name);
1028             for (const auto &method : methods)
1029             {
1030                 auto groupMethod = new TestCaseGroup(testCtx, method.name);
1031                 for (const auto &fateBits : fateBitPtrs)
1032                 {
1033 #ifndef CTS_USES_VULKANSC
1034                     for (const auto testSizeReq : {false, true})
1035 #else
1036                     const bool testSizeReq = false;
1037 #endif // CTS_USES_VULKANSC
1038                     {
1039                         TestConfig config;
1040                         config.fateBits             = fateBits;
1041                         config.incExtMemTypeFlags   = extMemTypeFlag.include;
1042                         config.createBits           = createBits;
1043                         config.useMethod2           = method.method;
1044                         config.testSizeRequirements = testSizeReq;
1045                         groupMethod->addChild(new MemoryRequirementsTest(
1046                             testCtx, ((testSizeReq ? "size_req_" : "") + bitsToString(*fateBits)).c_str(), config));
1047                     }
1048                 }
1049                 groupExtMemTypeFlags->addChild(groupMethod);
1050             }
1051             groupCreate->addChild(groupExtMemTypeFlags);
1052         }
1053         groupRoot->addChild(groupCreate);
1054     }
1055 
1056     return groupRoot;
1057 }
1058 } // namespace api
1059 } // namespace vkt
1060