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
28 #include "vkMemUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deFilePath.hpp"
34 #include "tcuTestLog.hpp"
35
36 #include <algorithm>
37 #include <array>
38 #include <functional>
39 #include <iostream>
40 #include <set>
41 #include <sstream>
42 #include <tuple>
43 #include <vector>
44
45 namespace vkt
46 {
47 namespace api
48 {
49 namespace
50 {
51
52 using namespace de;
53 using namespace vk;
54 using namespace tcu;
55
56 struct TestConfig;
57 struct InstanceConfig;
58
59 enum BufferFateFlagBits
60 {
61 Transfer = 0x01,
62 Storage = 0x02,
63 Other = 0x04,
64 AccStructure = 0x08,
65 Video = 0x10
66 };
67 typedef deUint32 BufferFateFlags;
68 typedef typename std::add_pointer<typename std::add_const<char>::type>::type cstr;
69 typedef u::BitsSet<BufferFateFlags, BufferFateFlagBits, cstr> BufferFateBits;
70
71 const BufferFateBits AvailableBufferFateBits
72 {
73 std::make_tuple(Transfer, "transfer_usage_bits" ),
74 std::make_tuple(Storage, "storage_usage_bits" ),
75 std::make_tuple(Other, "other_usage_bits" ),
76 std::make_tuple(AccStructure, "acc_struct_usage_bits" ),
77 std::make_tuple(Video, "video_usage_bits" ),
78 };
79
80 typedef u::BitsSet<VkBufferCreateFlags, VkBufferCreateFlagBits, cstr> BufferCreateBits;
81 typedef u::BitsSet<VkBufferUsageFlags, VkBufferUsageFlagBits, BufferFateFlagBits> BufferUsageBits;
82 typedef u::BitsSet<VkExternalMemoryHandleTypeFlags,
83 VkExternalMemoryHandleTypeFlagBits, cstr, bool> ExternalMemoryHandleBits;
84 typedef SharedPtr<BufferCreateBits> BufferCreateBitsPtr;
85 typedef SharedPtr<BufferUsageBits> BufferUsageBitsPtr;
86 typedef SharedPtr<ExternalMemoryHandleBits> ExternalMemoryHandleBitsPtr;
87
88 struct TestConfig
89 {
90 bool useMethod2;
91 SharedPtr<BufferCreateBits> createBits;
92 SharedPtr<BufferFateBits> fateBits;
93 bool incExtMemTypeFlags;
94 // Tests the buffer memory size requirement is less than or equal to the aligned size of the buffer.
95 // Requires VK_KHR_maintenance4 extension.
96 bool testSizeRequirements;
97 };
98 struct InstanceConfig
99 {
100 bool useMethod2;
101 SharedPtr<BufferCreateBits> createBits;
102 SharedPtr<BufferFateBits> fateBits;
103 SharedPtr<std::vector<BufferUsageBitsPtr>> usageFlags;
104 bool incExtMemTypeFlags;
105 SharedPtr<std::vector<ExternalMemoryHandleBitsPtr>> extMemHandleFlags;
106 bool testSizeRequirements;
107
InstanceConfigvkt::api::__anonc21762200111::InstanceConfig108 InstanceConfig(const TestConfig& conf)
109 : useMethod2 (conf.useMethod2)
110 , createBits (conf.createBits)
111 , fateBits (conf.fateBits)
112 , usageFlags (new std::vector<SharedPtr<BufferUsageBits>>)
113 , incExtMemTypeFlags (conf.incExtMemTypeFlags)
114 , extMemHandleFlags (new std::vector<SharedPtr<ExternalMemoryHandleBits>>)
115 , testSizeRequirements (conf.testSizeRequirements) {}
116 };
117
118 const BufferCreateBits AvailableBufferCreateBits
119 {
120 std::make_tuple(VkBufferCreateFlagBits(0), "no_flags" ),
121 std::make_tuple(VK_BUFFER_CREATE_PROTECTED_BIT, "protected" ),
122 std::make_tuple(VK_BUFFER_CREATE_SPARSE_BINDING_BIT, "sparse_binding" ),
123 std::make_tuple(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, "sparse_residency" ),
124 std::make_tuple(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, "sparse_aliased" ),
125 };
126
127 const BufferUsageBits AvailableBufferUsageBits
128 {
129 std::make_tuple(VK_BUFFER_USAGE_TRANSFER_SRC_BIT , Transfer ),
130 std::make_tuple(VK_BUFFER_USAGE_TRANSFER_DST_BIT , Transfer ),
131 std::make_tuple(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT , Storage ),
132 std::make_tuple(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT , Storage ),
133 std::make_tuple(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT , Storage ),
134 std::make_tuple(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT , Storage ),
135 std::make_tuple(VK_BUFFER_USAGE_INDEX_BUFFER_BIT , Storage ),
136 std::make_tuple(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT , Storage ),
137 std::make_tuple(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT , Other ),
138 std::make_tuple(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT , Other ),
139 std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR , Video ),
140 std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR , Video ),
141 std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT , Other ),
142 std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT , Other ),
143 std::make_tuple(VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT , Other ),
144 std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR , AccStructure ),
145 std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR , AccStructure ),
146 std::make_tuple(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR , AccStructure ),
147 std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR , Video ),
148 std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR , Video ),
149 };
150
151 #define INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS VkExternalMemoryHandleTypeFlagBits(0)
152 const ExternalMemoryHandleBits AvailableExternalMemoryHandleBits
153 {
154 std::make_tuple(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS , "no_flags", false ),
155 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT , "opaque_fd", false ),
156 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT , "opaque_win32", false ),
157 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT , "opaque_win32_kmt", false ),
158 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT , "d3d11_tex", false ),
159 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT , "d3d11_tex_kmt", false ),
160 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT , "d3d12_heap", false ),
161 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT , "d3d12_rsrc", false ),
162 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT , "dma_buf", false ),
163 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID , "android_hw", false ),
164 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT , "host_alloc", true ),
165 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT , "host_mapped", true ),
166 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA , "zircon_vmo", false ),
167 std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV , "roma_addr", false ),
168 };
169
170 template<class Flag, class Bit, class Str, class... Ignored>
bitsToString(const u::BitsSet<Flag,Bit,Str,Ignored...> & bits,const std::string & prefix=std::string ())171 std::string bitsToString (const u::BitsSet<Flag, Bit, Str, Ignored...>& bits,
172 const std::string& prefix = std::string())
173 {
174 DE_ASSERT(!bits.empty());
175 std::stringstream s;
176 s << prefix;
177 bool atLeastOne = false;
178 for (const auto& bit : bits) {
179 if (atLeastOne) s << '_';
180 s << std::get<1>(bit);
181 atLeastOne = true;
182 }
183 return s.str();
184 }
185
updateBufferCreateFlags(std::vector<BufferCreateBits> & flags)186 void updateBufferCreateFlags(std::vector<BufferCreateBits>& flags)
187 {
188 const auto& residencyBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT);
189 const auto& aliasedBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT);
190 const auto& bindingBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_BINDING_BIT);
191 const auto& protectedBit = AvailableBufferCreateBits.get(VK_BUFFER_CREATE_PROTECTED_BIT);
192 const auto& noneBit = AvailableBufferCreateBits.get(VkBufferCreateFlagBits(0));
193
194 // VUID-VkBufferCreateInfo-flags-00918 { if sparse residency or sparse aliased include sparse binding }
195 for (auto& bits : flags)
196 {
197 if (bits.contains(residencyBit) || bits.contains(aliasedBit))
198 bits.insert(bindingBit);
199 }
200
201 // VUID-VkBufferCreateInfo-None-01888 { if sparse residency, sparse aliased or sparse binding then flags must not include protected }
202 const typename BufferCreateBits::key_type disallowdBits[] { residencyBit, aliasedBit, bindingBit };
203 for (auto i = flags.begin(); i != flags.end();)
204 {
205 auto& bits = *i;
206 if (bits.contains(protectedBit))
207 {
208 for (const auto& disallowdBit : disallowdBits)
209 {
210 auto find = bits.find(disallowdBit);
211 if (find != bits.end())
212 bits.erase(find);
213 }
214 }
215 i = bits.empty() ? flags.erase(i) : std::next(i);
216 }
217
218 // since 0 is a valid VkBufferCreateFlagBits flag then remove it flags where it exists along with other non-zero flags
219 for (auto i = flags.begin(); i != flags.end(); ++i)
220 {
221 auto& bits = *i;
222 auto find = bits.find(noneBit);
223 if (find != bits.end() && bits.size() > 1)
224 {
225 bits.erase(find);
226 }
227 }
228
229 // remove duplicates
230 for (auto i = flags.begin(); i != flags.end(); ++i)
231 {
232 for (auto j = std::next(i); j != flags.end();)
233 j = (*i == *j) ? flags.erase(j) : std::next(j);
234 }
235 }
236
237 class BufferMemoryRequirementsInstance : public TestInstance
238 {
239 public:
BufferMemoryRequirementsInstance(Context & context,const InstanceConfig config)240 BufferMemoryRequirementsInstance (Context& context,
241 const InstanceConfig config)
242 : TestInstance (context)
243 , m_config (config) {}
244
245 virtual ~BufferMemoryRequirementsInstance (void) override = default;
246 virtual tcu::TestStatus iterate (void) override;
247
248 void getBufferMemoryRequirements (VkMemoryRequirements& result,
249 const DeviceInterface& vkd,
250 VkDevice device,
251 VkBuffer buffer) const;
252 void getBufferMemoryRequirements2 (VkMemoryRequirements& result,
253 const DeviceInterface& vkd,
254 VkDevice device,
255 VkBuffer buffer) const;
256 typedef void (BufferMemoryRequirementsInstance::* Method) (VkMemoryRequirements& result,
257 const DeviceInterface& intf,
258 VkDevice device,
259 VkBuffer buffer) const;
260 template<class T, class... AddArgs>
261 void* chainVkStructure (void* pNext,
262 const AddArgs&... addArgs) const;
263 private:
264 void logFailedSubtests (const std::vector<BufferCreateBitsPtr>& failCreateBits,
265 const std::vector<BufferUsageBitsPtr>& failUsageBits,
266 const std::vector<ExternalMemoryHandleBitsPtr>& failExtMemHandleBits) const;
267 const InstanceConfig m_config;
268 };
269
270 class MemoryRequirementsTest : public TestCase
271 {
272 public:
MemoryRequirementsTest(TestContext & testCtx,const std::string & name,const TestConfig testConfig)273 MemoryRequirementsTest (TestContext& testCtx,
274 const std::string& name,
275 const TestConfig testConfig)
276 : TestCase (testCtx, name, std::string())
277 , m_testConfig (testConfig)
278 , m_instConfig (testConfig) {}
279
280 virtual ~MemoryRequirementsTest (void) override = default;
281 virtual void checkSupport (Context& context) const override;
createInstance(Context & context) const282 virtual TestInstance* createInstance (Context& context) const override
283 {
284 return new BufferMemoryRequirementsInstance(context, m_instConfig);
285 }
286
287 private:
288 const TestConfig m_testConfig;
289 InstanceConfig m_instConfig;
290 };
291
292 struct Info
293 {
294 enum Type {
295 Create,
296 Usage
297 } m_type;
298 std::ostringstream m_str;
299 cstr m_file;
300 int m_line;
Infovkt::api::__anonc21762200111::Info301 template<class Msg> Info(Type type, const Msg& msg, cstr file, int line)
302 : m_type(type), m_str(), m_file(file), m_line(line) { m_str << msg; }
operator <<(std::ostringstream & str,const Info & info)303 friend std::ostringstream& operator<<(std::ostringstream& str, const Info& info) {
304 switch (info.m_type) {
305 case Create:
306 str << " Info (Create buffer with " << info.m_str.str() << " not supported by device at "
307 << de::FilePath(info.m_file).getBaseName() << ":" << info.m_line << ")";
308 break;
309 case Usage:
310 str << " Info (Create buffer with " << info.m_str.str() << " not supported by device at "
311 << de::FilePath(info.m_file).getBaseName() << ":" << info.m_line << ")";
312 break;
313 }
314 return str;
315 }
316 };
317 #define INFOCREATE(msg_) Info(Info::Create, (msg_), __FILE__, __LINE__)
318 #define INFOUSAGE(msg_) Info(Info::Usage, (msg_), __FILE__, __LINE__)
319
checkSupport(Context & context) const320 void MemoryRequirementsTest::checkSupport (Context& context) const
321 {
322 const InstanceInterface& intf = context.getInstanceInterface();
323 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
324 const std::vector<VkExtensionProperties> supportedExtensions = enumerateDeviceExtensionProperties(intf, physDevice, nullptr);
325
326 VkPhysicalDeviceProtectedMemoryFeatures protectedMemFeatures
327 {
328 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, // VkStructureType sType;
329 nullptr, // void* pNext;
330 VK_FALSE // VkBool32 protectedMemory;
331 };
332 VkPhysicalDeviceFeatures2 extFeatures
333 {
334 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType sType;
335 &protectedMemFeatures, // void* pNext;
336 {} // VkPhysicalDeviceFeatures features;
337 };
338 intf.getPhysicalDeviceFeatures2(physDevice, &extFeatures);
339
340 const VkPhysicalDeviceFeatures& features = extFeatures.features;
341 const VkBool32& protectedMemFeatureEnabled = protectedMemFeatures.protectedMemory;
342
343
344 // check the creating bits
345 {
346 std::ostringstream str;
347 bool notSupported = false;
348 const auto& createBits = *m_testConfig.createBits;
349
350 if (createBits.contains(VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (VK_FALSE == features.sparseBinding))
351 {
352 if (notSupported) str << std::endl;
353 str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_BINDING_BIT));
354 notSupported = true;
355 }
356 if (createBits.contains(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (VK_FALSE == features.sparseResidencyBuffer))
357 {
358 if (notSupported) str << std::endl;
359 str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT));
360 notSupported = true;
361 }
362 if (createBits.contains(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (VK_FALSE == features.sparseResidencyAliased))
363 {
364 if (notSupported) str << std::endl;
365 str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT));
366 notSupported = true;
367 }
368 if (createBits.contains(VK_BUFFER_CREATE_PROTECTED_BIT) && (VK_FALSE == protectedMemFeatureEnabled))
369 {
370 if (notSupported) str << std::endl;
371 str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_PROTECTED_BIT));
372 notSupported = true;
373 }
374 if (notSupported)
375 {
376 std::cout << str.str() << std::endl;
377 TCU_THROW(NotSupportedError, "One or more create buffer flags not supported by device");
378 }
379 }
380
381 // check the usage bits and build instance input
382 {
383 std::vector<BufferUsageBits> usageFlags;
384 for (const auto& bit : *m_testConfig.fateBits)
385 {
386 auto fate = m_testConfig.fateBits->extract(bit);
387 std::vector<VkBufferUsageFlags> usageHints;
388 std::vector<BufferUsageBits> usageFlagsTmp;
389 u::combine(usageFlagsTmp, AvailableBufferUsageBits.select<1>(fate), usageHints);
390 u::mergeFlags(usageFlags, usageFlagsTmp);
391 }
392
393 std::ostringstream str;
394 std::array<bool, 5> msgs;
395 bool notSupported = false;
396 int entryCount = 0;
397 msgs.fill(false);
398
399 for (auto i = usageFlags.begin(); i != usageFlags.end();)
400 {
401 notSupported = false;
402
403 if (i->any({VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
404 VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR})
405 && !isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_acceleration_structure")))
406 {
407 if (!msgs[0])
408 {
409 if (entryCount++) str << std::endl;
410 str << INFOUSAGE("VK_KHR_acceleration_structure not supported by device");
411 msgs[0] = true;
412 }
413 notSupported = true;
414 }
415
416 if (i->contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
417 && !isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_buffer_device_address")))
418 {
419 if (!msgs[1])
420 {
421 if (entryCount++) str << std::endl;
422 str << INFOUSAGE("VK_EXT_buffer_device_address not supported by device");
423 msgs[1] = true;
424 }
425 notSupported = true;
426 }
427
428 if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR,
429 VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
430 {
431
432 }
433
434 i = notSupported ? usageFlags.erase(i) : std::next(i);
435 }
436
437 // remove duplicates
438 for (auto i = usageFlags.begin(); i != usageFlags.end(); ++i)
439 {
440 for (auto j = std::next(i); j != usageFlags.end();)
441 j = (*i == *j) ? usageFlags.erase(j) : std::next(j);
442 }
443
444 if (usageFlags.empty())
445 {
446 std::cout << str.str() << std::endl;
447 TCU_THROW(NotSupportedError, "One or more buffer usage flags not supported by device");
448 }
449 else
450 {
451 if (entryCount > 0)
452 {
453 std::cout << str.str() << std::endl;
454 }
455 DE_ASSERT(m_instConfig.usageFlags.get());
456 m_instConfig.usageFlags->resize(usageFlags.size());
457 std::transform(usageFlags.begin(), usageFlags.end(), m_instConfig.usageFlags->begin(),
458 [](BufferUsageBits& bits){ return BufferUsageBits::makeShared(std::move(bits)); });
459 }
460 }
461
462 // check the external memory handle type bits and build instance input
463 {
464 std::vector<ExternalMemoryHandleBits> extMemHandleFlags;
465 if (m_testConfig.incExtMemTypeFlags)
466 extMemHandleFlags.push_back({AvailableExternalMemoryHandleBits.get(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS)});
467 else
468 {
469 std::vector<VkExternalMemoryHandleTypeFlags> handleHints;
470 std::vector<ExternalMemoryHandleBits> handleFlagsTmp;
471 u::combine(handleFlagsTmp, AvailableExternalMemoryHandleBits.select<2>(true), handleHints);
472 u::mergeFlags(extMemHandleFlags, handleFlagsTmp);
473 }
474
475 DE_ASSERT(m_instConfig.extMemHandleFlags.get());
476 m_instConfig.extMemHandleFlags->resize(extMemHandleFlags.size());
477 std::transform(extMemHandleFlags.begin(), extMemHandleFlags.end(), m_instConfig.extMemHandleFlags->begin(),
478 [](ExternalMemoryHandleBits& bits){ return ExternalMemoryHandleBits::makeShared(std::move(bits)); });
479 }
480
481 if (m_testConfig.testSizeRequirements)
482 {
483 if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance4"))
484 TCU_THROW(NotSupportedError, "VK_KHR_maintenance4 not supported");
485 }
486 }
487
logFailedSubtests(const std::vector<BufferCreateBitsPtr> & failCreateBits,const std::vector<BufferUsageBitsPtr> & failUsageBits,const std::vector<ExternalMemoryHandleBitsPtr> & failExtMemHandleBits) const488 void BufferMemoryRequirementsInstance::logFailedSubtests (const std::vector<BufferCreateBitsPtr>& failCreateBits,
489 const std::vector<BufferUsageBitsPtr>& failUsageBits,
490 const std::vector<ExternalMemoryHandleBitsPtr>& failExtMemHandleBits) const
491 {
492 const deUint32 flagCount = deUint32(failCreateBits.size());
493 TestLog& log = m_context.getTestContext().getLog();
494 deUint32 entries = 0;
495
496 DE_ASSERT(flagCount && flagCount == failUsageBits.size() && flagCount == failExtMemHandleBits.size());
497
498 log << TestLog::Section("Failed", "Failed subtests");
499
500 for (deUint32 i = 0; i < flagCount; ++i)
501 {
502 {
503 log << TestLog::Section("VkBufferCreateFlags", "Buffer create flags");
504 auto msg = log << TestLog::Message;
505 entries = 0;
506 for (const auto& createBit : *failCreateBits[i])
507 {
508 if (entries++) msg << " ";
509 const VkBufferCreateFlags flags = BufferCreateBits::extract(createBit);
510 if (flags == 0)
511 msg << "0";
512 else msg << getBufferCreateFlagsStr(flags);
513 }
514 msg << TestLog::EndMessage << TestLog::EndSection;
515 }
516
517 {
518 log << TestLog::Section("VkBufferUsageFlags", "Buffer usage flags");
519 auto msg = log << TestLog::Message;
520 entries = 0;
521 for (const auto& usageBit : *failUsageBits[i])
522 {
523 if (entries++) msg << " ";
524 msg << getBufferUsageFlagsStr(BufferUsageBits::extract(usageBit));
525 }
526 msg << TestLog::EndMessage << TestLog::EndSection;
527 }
528
529 {
530 log << TestLog::Section("VkExternalMemoryHandleTypeFlags", "External memory handle type flags");
531 auto msg = log << TestLog::Message;
532 entries = 0;
533 for (const auto& extMemHandleTypeBit : *failExtMemHandleBits[i])
534 {
535 if (entries++) msg << " ";
536 msg << getExternalMemoryHandleTypeFlagsStr(ExternalMemoryHandleBits::extract(extMemHandleTypeBit));
537 }
538 msg << TestLog::EndMessage << TestLog::EndSection;
539 }
540 }
541
542 log << TestLog::EndSection;
543 }
544
getBufferMemoryRequirements2(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const545 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements2 (VkMemoryRequirements& result,
546 const DeviceInterface& vkd,
547 VkDevice device,
548 VkBuffer buffer) const
549 {
550 VkMemoryDedicatedRequirements dedicatedRequirements =
551 {
552 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, // VkStructureType sType;
553 nullptr, // const void* pNext;
554 VK_FALSE, // VkBool32 prefersDedicatedAllocation
555 VK_FALSE // VkBool32 requiresDedicatedAllocation
556 };
557
558 VkMemoryRequirements2 desiredRequirements =
559 {
560 VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType sType
561 &dedicatedRequirements, // void* pNext
562 result // VkMemoryRequirements memoryRequirements
563 };
564
565 VkBufferMemoryRequirementsInfo2 requirementsInfo =
566 {
567 VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType sType
568 nullptr, // const void* pNext
569 buffer // VkBuffer buffer
570 };
571
572 vkd.getBufferMemoryRequirements2(device, &requirementsInfo, &desiredRequirements);
573
574 result = desiredRequirements.memoryRequirements;
575 }
576
getBufferMemoryRequirements(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const577 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements (VkMemoryRequirements& result,
578 const DeviceInterface& vkd,
579 VkDevice device,
580 VkBuffer buffer) const
581 {
582 vkd.getBufferMemoryRequirements(device, buffer, &result);
583 }
584
585 template<> void*
chainVkStructure(void * pNext,const VkExternalMemoryHandleTypeFlags & handleTypes) const586 BufferMemoryRequirementsInstance::chainVkStructure<VkExternalMemoryBufferCreateInfo> (void* pNext, const VkExternalMemoryHandleTypeFlags& handleTypes) const
587 {
588 static VkExternalMemoryBufferCreateInfo memInfo{};
589 memInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
590 memInfo.pNext = pNext;
591 memInfo.handleTypes = handleTypes;
592
593 return &memInfo;
594 }
595
chainVkStructure(void * pNext) const596 template<> void* BufferMemoryRequirementsInstance::chainVkStructure<VkVideoProfilesKHR> (void* pNext) const
597 {
598 static const VkVideoProfileKHR videoProfile
599 {
600 VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR, // VkStructureType sType;
601 nullptr, // void* pNext;
602 VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR, // VkVideoCodecOperationFlagBitsKHR videoCodecOperation;
603 VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR, // VkVideoChromaSubsamplingFlagsKHR chromaSubsampling;
604 VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR, // VkVideoComponentBitDepthFlagsKHR lumaBitDepth;
605 VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR // VkVideoComponentBitDepthFlagsKHR chromaBitDepth;
606 };
607
608 static VkVideoProfilesKHR profiles;
609 profiles.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR;
610 profiles.pNext = pNext;
611 profiles.profileCount = 1u;
612 profiles.pProfiles = &videoProfile;
613
614 return &profiles;
615 }
616
iterate(void)617 TestStatus BufferMemoryRequirementsInstance::iterate (void)
618 {
619 const DeviceInterface& vkd = m_context.getDeviceInterface();
620 const VkDevice device = m_context.getDevice();
621 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
622 const Method method = m_config.useMethod2
623 ? &BufferMemoryRequirementsInstance::getBufferMemoryRequirements2
624 : &BufferMemoryRequirementsInstance::getBufferMemoryRequirements;
625
626 deUint32 passCount = 0;
627 deUint32 failCount = 0;
628 std::vector<BufferCreateBitsPtr> failCreateBits;
629 std::vector<BufferUsageBitsPtr> failUsageBits;
630 std::vector<ExternalMemoryHandleBitsPtr> failExtMemHandleBits;
631
632 DE_ASSERT(!m_config.createBits->empty());
633 const VkBufferCreateFlags infoCreateFlags = *m_config.createBits;
634 {
635 DE_ASSERT(!m_config.usageFlags->empty());
636 for (auto u = m_config.usageFlags->cbegin(); u != m_config.usageFlags->cend(); ++u)
637 {
638 const VkBufferUsageFlags infoUsageFlags = *(u->get());
639
640 DE_ASSERT(!m_config.extMemHandleFlags->empty());
641 for (auto m = m_config.extMemHandleFlags->cbegin(); m != m_config.extMemHandleFlags->cend(); ++m)
642 {
643 const VkExternalMemoryHandleTypeFlags handleFlags = *(m->get());
644
645 void* pNext = nullptr;
646
647 if (m_config.fateBits->contains(BufferFateFlagBits::Video))
648 {
649 pNext = chainVkStructure<VkVideoProfilesKHR>(pNext);
650 }
651 if (m_config.incExtMemTypeFlags)
652 {
653 pNext = chainVkStructure<VkExternalMemoryBufferCreateInfo>(pNext, handleFlags);
654 }
655 VkBufferCreateInfo createInfo
656 {
657 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
658 pNext, // const void* pNext;
659 infoCreateFlags, // VkBufferCreateFlags flags;
660 4096u, // VkDeviceSize size;
661 infoUsageFlags, // VkBufferUsageFlags usage;
662 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
663 1u, // uint32_t queueFamilyIndexCount;
664 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
665 };
666
667 if (m_config.testSizeRequirements)
668 {
669 VkPhysicalDeviceMaintenance4PropertiesKHR maintenance4Properties =
670 {
671 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR, // VkStructureType sType;
672 DE_NULL, // void* pNext;
673 0u // VkDeviceSize maxBufferSize;
674 };
675
676 VkPhysicalDeviceProperties2 physicalDeviceProperties2 =
677 {
678 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType;
679 &maintenance4Properties, // void* pNext;
680 {}, // VkPhysicalDeviceProperties properties;
681 };
682
683 m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties2);
684
685 const VkDeviceSize maxBufferSize = maintenance4Properties.maxBufferSize;
686 DE_ASSERT(maxBufferSize > 0);
687 VkDeviceSize N = 0;
688
689 while ((1ull << N) + 1 < maxBufferSize)
690 {
691 createInfo.size = (1ull << N) + 1;
692
693 try
694 {
695 Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
696
697 VkMemoryRequirements reqs{};
698 (this->*method)(reqs, vkd, device, *buffer);
699
700 if (reqs.size <= static_cast<VkDeviceSize>(deAlign64(static_cast<deInt64>(createInfo.size), static_cast<deInt64>(reqs.alignment))))
701 {
702 ++passCount;
703 } else
704 {
705 ++failCount;
706 failCreateBits.emplace_back(m_config.createBits);
707 failUsageBits.emplace_back(*u);
708 failExtMemHandleBits.emplace_back(*m);
709 }
710
711 N++;
712 }
713 catch (const vk::OutOfMemoryError&)
714 {
715 break;
716 }
717 }
718 }
719 else
720 {
721 Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
722
723 VkMemoryRequirements reqs{};
724 (this->*method)(reqs, vkd, device, *buffer);
725 if (reqs.memoryTypeBits)
726 ++passCount;
727 else
728 {
729 ++failCount;
730 failCreateBits.emplace_back(m_config.createBits);
731 failUsageBits.emplace_back(*u);
732 failExtMemHandleBits.emplace_back(*m);
733 }
734 }
735 }
736 }
737 }
738
739 if (failCount)
740 {
741 logFailedSubtests(failCreateBits, failUsageBits, failExtMemHandleBits);
742 return TestStatus::fail(std::to_string(failCount));
743 }
744
745 return TestStatus::pass(std::to_string(passCount));
746 }
747
748 } // unnamed namespace
749
createBufferMemoryRequirementsTests(tcu::TestContext & testCtx)750 tcu::TestCaseGroup* createBufferMemoryRequirementsTests (tcu::TestContext& testCtx)
751 {
752 cstr nilstr = "";
753
754 struct
755 {
756 bool include;
757 cstr name;
758 } const extMemTypeFlags[] { { false, "ext_mem_flags_excluded" }, { true, "ext_mem_flags_included" } };
759
760 struct
761 {
762 bool method;
763 cstr name;
764 } const methods[] { { false, "method1" }, { true, "method2" } };
765
766 std::vector<SharedPtr<BufferCreateBits>> createBitPtrs;
767 {
768 std::vector<VkBufferCreateFlags> hints;
769 std::vector<BufferCreateBits> createFlags;
770 u::combine(createFlags, AvailableBufferCreateBits, hints);
771 updateBufferCreateFlags(createFlags);
772 createBitPtrs.resize(createFlags.size());
773 std::transform(createFlags.begin(), createFlags.end(), createBitPtrs.begin(),
774 [](BufferCreateBits& bits) { return BufferCreateBits::makeShared(std::move(bits)); });
775 }
776
777 std::vector<SharedPtr<BufferFateBits>> fateBitPtrs;
778 {
779 // An excerpt above has been disabled consciously for the sake of computational complexity.
780 // Enabled block does the same things sequentially, it doesn't create cartesian product of combination of bits.
781 #if 0
782 std::vector<BufferFateFlags> hints;
783 std::vector<BufferFateBits> bufferFateFlags;
784 u::combine(bufferFateFlags, AvailableBufferFateBits, hints);
785 fateBitPtrs.resize(bufferFateFlags.size());
786 std::transform(bufferFateFlags.begin(), bufferFateFlags.end(), fateBitPtrs.begin(),
787 [](BufferFateBits& bits) { return BufferFateBits::makeShared(std::move(bits)); });
788 #else
789 fateBitPtrs.resize(AvailableBufferFateBits.size());
790 std::transform(AvailableBufferFateBits.begin(), AvailableBufferFateBits.end(), fateBitPtrs.begin(),
791 [](const typename BufferFateBits::value_type& bit) { return BufferFateBits::makeShared(bit); });
792 #endif
793 }
794
795 auto groupRoot = new TestCaseGroup(testCtx, "buffer_memory_requirements", "vkGetBufferMemoryRequirements*(...) routines tests.");
796 for (const auto& createBits : createBitPtrs)
797 {
798 auto groupCreate = new TestCaseGroup(testCtx, bitsToString(*createBits, "create_").c_str(), nilstr);
799 for (const auto& extMemTypeFlag : extMemTypeFlags)
800 {
801 auto groupExtMemTypeFlags = new TestCaseGroup(testCtx, extMemTypeFlag.name, nilstr);
802 for (const auto& method : methods)
803 {
804 auto groupMethod = new TestCaseGroup(testCtx, method.name, nilstr);
805 for (const auto& fateBits : fateBitPtrs)
806 {
807 for (const auto testSizeReq : {false, true})
808 {
809 TestConfig config;
810 config.fateBits = fateBits;
811 config.incExtMemTypeFlags = extMemTypeFlag.include;
812 config.createBits = createBits;
813 config.useMethod2 = method.method;
814 config.testSizeRequirements = testSizeReq;
815 groupMethod->addChild(new MemoryRequirementsTest(testCtx, ((testSizeReq ? "size_req_" : "") + bitsToString(*fateBits)).c_str(), config));
816 }
817 }
818 groupExtMemTypeFlags->addChild(groupMethod);
819 }
820 groupCreate->addChild(groupExtMemTypeFlags);
821 }
822 groupRoot->addChild(groupCreate);
823 }
824
825 return groupRoot;
826 }
827 } // api
828 } // vkt
829