1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Khronos Group
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 API Maintenance3 Check test - checks structs and function from VK_KHR_maintenance3
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuTestLog.hpp"
25
26 #include "vkQueryUtil.hpp"
27
28 #include "vktApiMaintenance3Check.hpp"
29 #include "vktTestCase.hpp"
30
31 #include <sstream>
32 #include <limits>
33 #include <utility>
34 #include <algorithm>
35 #include <map>
36 #include <set>
37
38 using namespace vk;
39
40 namespace vkt
41 {
42
43 namespace api
44 {
45
46 namespace
47 {
48 using ::std::string;
49 using ::std::vector;
50 using ::std::map;
51 using ::std::set;
52 using ::std::ostringstream;
53 using ::std::make_pair;
54
55 typedef vk::VkPhysicalDeviceProperties DevProp1;
56 typedef vk::VkPhysicalDeviceProperties2 DevProp2;
57 typedef vk::VkPhysicalDeviceMaintenance3Properties MaintDevProp3;
58 typedef vk::VkPhysicalDeviceFeatures2 DevFeat2;
59 typedef vk::VkPhysicalDeviceInlineUniformBlockFeaturesEXT DevIubFeat;
60 typedef vk::VkPhysicalDeviceInlineUniformBlockPropertiesEXT DevIubProp;
61
62 // These variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
63 constexpr deUint32 maxMemoryAllocationSize = 1073741824u;
64 constexpr deUint32 maxDescriptorsInSet = 1024u;
65 constexpr deUint32 maxReasonableInlineUniformBlocks = 64u;
66
67 using TypeSet = set<vk::VkDescriptorType>;
68
69 // Structure representing an implementation limit, like maxPerStageDescriptorSamplers. It has a maximum value
70 // obtained at runtime and a remaining number of descriptors, which starts with the same count and decreases
71 // as we assign descriptor counts to the different types. A limit is affected by (or itself affects) one or more
72 // descriptor types. Note a type may be involved in several limits, and a limit may affect several types.
73 struct Limit
74 {
Limitvkt::api::__anona5ad014a0111::Limit75 Limit(const string& name_, deUint32 maxValue_, const TypeSet& affectedTypes_)
76 : name(name_), maxValue(maxValue_), remaining(maxValue_), affectedTypes(affectedTypes_)
77 {}
78
79 const string name;
80 const deUint32 maxValue;
81 deUint32 remaining;
82 const TypeSet affectedTypes;
83 };
84
85 // Structure representing how many descriptors have been assigned to the given type. The type is "alive" during
86 // descriptor count assignment if more descriptors can be added to the type without hitting any limit affected
87 // by the type. Once at least one of the limits is reached, no more descriptors can be assigned to the type and
88 // the type is no longer considered "alive".
89 struct TypeState
90 {
TypeStatevkt::api::__anona5ad014a0111::TypeState91 TypeState(vk::VkDescriptorType type_)
92 : type(type_), alive(true), count(0u)
93 {}
94
95 const vk::VkDescriptorType type;
96 bool alive;
97 deUint32 count;
98 };
99
100 using TypeCounts = map<vk::VkDescriptorType, TypeState>;
101 using LimitsVector = vector<Limit>;
102
103 // Get the subset of alive types from the given map.
getAliveTypes(const TypeCounts & typeCounts)104 TypeSet getAliveTypes (const TypeCounts& typeCounts)
105 {
106 TypeSet aliveTypes;
107 for (const auto& typeCount : typeCounts)
108 {
109 if (typeCount.second.alive)
110 aliveTypes.insert(typeCount.first);
111 }
112 return aliveTypes;
113 }
114
115 // Get the subset of alive types for a specific limit, among the set of types affected by the limit.
getAliveTypesForLimit(const Limit & limit,const TypeSet & aliveTypes)116 TypeSet getAliveTypesForLimit (const Limit& limit, const TypeSet& aliveTypes)
117 {
118 TypeSet subset;
119 for (const auto& type : limit.affectedTypes)
120 {
121 if (aliveTypes.find(type) != aliveTypes.end())
122 subset.insert(type);
123 }
124 return subset;
125 }
126
127 // Distribute descriptor counts as evenly as possible among the given set of types, taking into account the
128 // given limits.
distributeCounts(LimitsVector & limits,TypeCounts & typeCounts)129 void distributeCounts (LimitsVector& limits, TypeCounts& typeCounts)
130 {
131 using IncrementsMap = map<vk::VkDescriptorType, deUint32>;
132 TypeSet aliveTypes;
133
134 while ((aliveTypes = getAliveTypes(typeCounts)).size() > 0u)
135 {
136 // Calculate the maximum increment per alive descriptor type. This involves iterating over the limits and
137 // finding out how many more descriptors can be distributed among the affected types that are still alive
138 // for the limit. For each type, remember the lowest possible increment.
139 IncrementsMap increments;
140 for (const auto& type : aliveTypes)
141 increments[type] = std::numeric_limits<deUint32>::max();
142
143 TypeSet aliveTypesForLimit;
144
145 for (const auto& limit : limits)
146 {
147 if (limit.remaining == 0u)
148 continue;
149
150 aliveTypesForLimit = getAliveTypesForLimit(limit, aliveTypes);
151 if (aliveTypesForLimit.empty())
152 continue;
153
154 // Distribute remaining count evenly among alive types.
155 deUint32 maxIncrement = limit.remaining / static_cast<deUint32>(aliveTypesForLimit.size());
156 if (maxIncrement == 0u)
157 {
158 // More types than remaining descriptors. Assign 1 to the first affected types and 0 to the rest.
159 deUint32 remaining = limit.remaining;
160 for (const auto& type : aliveTypesForLimit)
161 {
162 if (remaining > 0u && increments[type] > 0u)
163 {
164 increments[type] = 1u;
165 --remaining;
166 }
167 else
168 {
169 increments[type] = 0u;
170 }
171 }
172 }
173 else
174 {
175 // Find the lowest possible increment taking into account all limits.
176 for (const auto& type : aliveTypesForLimit)
177 {
178 if (increments[type] > maxIncrement)
179 increments[type] = maxIncrement;
180 }
181 }
182 }
183
184 // Apply the calculated increments per descriptor type, decreasing the remaining descriptors for each
185 // limit affected by the type, and switching types to the not-alive state when a limit is hit.
186 for (const auto& inc : increments)
187 {
188 const vk::VkDescriptorType& type = inc.first;
189 const deUint32& increment = inc.second;
190
191 // Increase type count.
192 auto iter = typeCounts.find(type);
193 DE_ASSERT(iter != typeCounts.end());
194 iter->second.count += increment;
195
196 for (auto& limit : limits)
197 {
198 // Decrease remaining descriptors for affected limits.
199 if (limit.affectedTypes.find(type) != limit.affectedTypes.end())
200 {
201 DE_ASSERT(increment <= limit.remaining);
202 limit.remaining -= increment;
203 }
204 if (limit.remaining == 0u)
205 {
206 // Limit hit, switch affected types to not-alive.
207 for (const auto& affectedType : limit.affectedTypes)
208 {
209 auto tc = typeCounts.find(affectedType);
210 if (tc != typeCounts.end())
211 tc->second.alive = false;
212 }
213 }
214 }
215 }
216 }
217 }
218
219 // Create a limits vector based on runtime limit information for the device.
buildLimitsVector(const DevProp1 & prop1,const DevIubProp & iubProp,const MaintDevProp3 & maintProp3)220 LimitsVector buildLimitsVector (const DevProp1& prop1, const DevIubProp& iubProp, const MaintDevProp3& maintProp3)
221 {
222 static const TypeSet samplerTypes = { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_DESCRIPTOR_TYPE_SAMPLER };
223 static const TypeSet sampledImageTypes = { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER };
224 static const TypeSet uniformBufferTypes = { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC };
225 static const TypeSet storageBufferTypes = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC };
226 static const TypeSet storageImageTypes = { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER };
227 static const TypeSet inputAttachmentTypes = { vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT };
228 static const TypeSet inlineUniformBlockTypes = { vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT };
229 static const TypeSet dynamicUniformBuffer = { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC };
230 static const TypeSet dynamicStorageBuffer = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC };
231 static const TypeSet allTypesButIUB = {
232 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
233 vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
234 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
235 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
236 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
237 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
238 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
239 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
240 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
241 vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
242 };
243 static const TypeSet allTypes = {
244 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
245 vk::VK_DESCRIPTOR_TYPE_SAMPLER,
246 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
247 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
248 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
249 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
250 vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
251 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
252 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
253 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
254 vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
255 vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT,
256 };
257
258 LimitsVector limits = {
259 {
260 "maxPerStageDescriptorSamplers",
261 prop1.limits.maxPerStageDescriptorSamplers,
262 samplerTypes
263 },
264 {
265 "maxDescriptorSetSamplers",
266 prop1.limits.maxDescriptorSetSamplers,
267 samplerTypes
268 },
269 {
270 "maxPerStageDescriptorSampledImages",
271 prop1.limits.maxPerStageDescriptorSampledImages,
272 sampledImageTypes
273 },
274 {
275 "maxDescriptorSetSampledImages",
276 prop1.limits.maxDescriptorSetSampledImages,
277 sampledImageTypes
278 },
279 {
280 "maxPerStageDescriptorUniformBuffers",
281 prop1.limits.maxPerStageDescriptorUniformBuffers,
282 uniformBufferTypes
283 },
284 {
285 "maxDescriptorSetUniformBuffers",
286 prop1.limits.maxDescriptorSetUniformBuffers,
287 uniformBufferTypes
288 },
289 {
290 "maxPerStageDescriptorStorageBuffers",
291 prop1.limits.maxPerStageDescriptorStorageBuffers,
292 storageBufferTypes
293 },
294 {
295 "maxDescriptorSetStorageBuffers",
296 prop1.limits.maxDescriptorSetStorageBuffers,
297 storageBufferTypes
298 },
299 {
300 "maxPerStageDescriptorStorageImages",
301 prop1.limits.maxPerStageDescriptorStorageImages,
302 storageImageTypes
303 },
304 {
305 "maxDescriptorSetStorageImages",
306 prop1.limits.maxDescriptorSetStorageImages,
307 storageImageTypes
308 },
309 {
310 "maxPerStageDescriptorInputAttachments",
311 prop1.limits.maxPerStageDescriptorInputAttachments,
312 inputAttachmentTypes
313 },
314 {
315 "maxDescriptorSetInputAttachments",
316 prop1.limits.maxDescriptorSetInputAttachments,
317 inputAttachmentTypes
318 },
319 {
320 "maxDescriptorSetUniformBuffersDynamic",
321 prop1.limits.maxDescriptorSetUniformBuffersDynamic,
322 dynamicUniformBuffer
323 },
324 {
325 "maxDescriptorSetStorageBuffersDynamic",
326 prop1.limits.maxDescriptorSetStorageBuffersDynamic,
327 dynamicStorageBuffer
328 },
329 {
330 "maxPerStageDescriptorInlineUniformBlocks",
331 iubProp.maxPerStageDescriptorInlineUniformBlocks,
332 inlineUniformBlockTypes
333 },
334 {
335 "maxDescriptorSetInlineUniformBlocks",
336 iubProp.maxDescriptorSetInlineUniformBlocks,
337 inlineUniformBlockTypes
338 },
339 {
340 "maxPerStageResources",
341 prop1.limits.maxPerStageResources,
342 allTypesButIUB
343 },
344 {
345 "maxPerSetDescriptors",
346 maintProp3.maxPerSetDescriptors,
347 allTypes
348 },
349 };
350
351 return limits;
352 }
353
354 // Create a vector of bindings by constructing the system limits and distributing descriptor counts.
calculateBindings(const DevProp1 & prop1,const DevIubProp & iubProp,const MaintDevProp3 & maintProp3,const vector<vk::VkDescriptorType> & types)355 vector<vk::VkDescriptorSetLayoutBinding> calculateBindings(const DevProp1& prop1, const DevIubProp& iubProp, const MaintDevProp3& maintProp3, const vector<vk::VkDescriptorType> &types)
356 {
357 LimitsVector limits = buildLimitsVector(prop1, iubProp, maintProp3);
358 TypeCounts typeCounts;
359
360 for (const auto& type : types)
361 typeCounts.emplace(make_pair(type, TypeState(type)));
362
363 distributeCounts(limits, typeCounts);
364
365 deUint32 bindingNumber = 0u;
366 vector<vk::VkDescriptorSetLayoutBinding> bindings;
367 for (const auto& tc : typeCounts)
368 {
369 if (tc.first != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
370 {
371 vk::VkDescriptorSetLayoutBinding b;
372 b.binding = bindingNumber;
373 b.descriptorCount = tc.second.count;
374 b.descriptorType = tc.first;
375 b.pImmutableSamplers = DE_NULL;
376 b.stageFlags = vk::VK_SHADER_STAGE_ALL;
377
378 bindings.push_back(b);
379 }
380 else
381 {
382 // Inline uniform blocks are special because descriptorCount represents the size of that block.
383 // The only way of creating several blocks is by adding more structures to the list instead of creating an array.
384 size_t firstAdded = bindings.size();
385 bindings.resize(firstAdded + tc.second.count);
386 for (deUint32 i = 0u; i < tc.second.count; ++i)
387 {
388 vk::VkDescriptorSetLayoutBinding& b = bindings[firstAdded + i];
389 b.binding = bindingNumber + i;
390 b.descriptorCount = 4u; // For inline uniform blocks, this must be a multiple of 4 according to the spec.
391 b.descriptorType = tc.first;
392 b.pImmutableSamplers = DE_NULL;
393 b.stageFlags = vk::VK_SHADER_STAGE_ALL;
394 }
395 }
396 bindingNumber += tc.second.count;
397 }
398
399 return bindings;
400 }
401
402 // Get a textual description with descriptor counts per type.
getBindingsDescription(const vector<VkDescriptorSetLayoutBinding> & bindings)403 string getBindingsDescription (const vector<VkDescriptorSetLayoutBinding>& bindings)
404 {
405 map<vk::VkDescriptorType, deUint32> typeCount;
406 deUint32 totalCount = 0u;
407 deUint32 count;
408 for (const auto& b : bindings)
409 {
410 auto iter = typeCount.find(b.descriptorType);
411 if (iter == typeCount.end())
412 iter = typeCount.insert(make_pair(b.descriptorType, (deUint32)0)).first;
413 count = ((b.descriptorType == vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1u : b.descriptorCount);
414 iter->second += count;
415 totalCount += count;
416 }
417
418 deUint32 i = 0;
419 ostringstream combStr;
420
421 combStr << "{ Descriptors: " << totalCount << ", [";
422 for (const auto& tc : typeCount)
423 combStr << (i++ ? ", " : " ") << tc.first << ": " << tc.second;
424 combStr << " ] }";
425
426 return combStr.str();
427 }
428
429 class Maintenance3StructTestInstance : public TestInstance
430 {
431 public:
Maintenance3StructTestInstance(Context & ctx)432 Maintenance3StructTestInstance (Context& ctx)
433 : TestInstance (ctx)
434 {}
iterate(void)435 virtual tcu::TestStatus iterate (void)
436 {
437 tcu::TestLog& log = m_context.getTestContext().getLog();
438
439 // set values to be a bit smaller than required minimum values
440 MaintDevProp3 maintProp3 =
441 {
442 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, //VkStructureType sType;
443 DE_NULL, //void* pNext;
444 maxDescriptorsInSet - 1u, //deUint32 maxPerSetDescriptors;
445 maxMemoryAllocationSize - 1u //VkDeviceSize maxMemoryAllocationSize;
446 };
447
448 DevProp2 prop2;
449 deMemset(&prop2, 0, sizeof(prop2)); // zero the structure
450 prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
451 prop2.pNext = &maintProp3;
452
453 m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &prop2);
454
455 if (maintProp3.maxMemoryAllocationSize < maxMemoryAllocationSize)
456 return tcu::TestStatus::fail("Fail");
457
458 if (maintProp3.maxPerSetDescriptors < maxDescriptorsInSet)
459 return tcu::TestStatus::fail("Fail");
460
461 log << tcu::TestLog::Message << "maxMemoryAllocationSize: " << maintProp3.maxMemoryAllocationSize << tcu::TestLog::EndMessage;
462 log << tcu::TestLog::Message << "maxPerSetDescriptors: " << maintProp3.maxPerSetDescriptors << tcu::TestLog::EndMessage;
463 return tcu::TestStatus::pass("Pass");
464 }
465 };
466
467 class Maintenance3StructTestCase : public TestCase
468 {
469 public:
Maintenance3StructTestCase(tcu::TestContext & testCtx)470 Maintenance3StructTestCase (tcu::TestContext& testCtx)
471 : TestCase(testCtx, "maintenance3_properties", "tests VkPhysicalDeviceMaintenance3Properties struct")
472 {}
473
~Maintenance3StructTestCase(void)474 virtual ~Maintenance3StructTestCase (void)
475 {}
checkSupport(Context & ctx) const476 virtual void checkSupport (Context& ctx) const
477 {
478 ctx.requireDeviceFunctionality("VK_KHR_maintenance3");
479 }
createInstance(Context & ctx) const480 virtual TestInstance* createInstance (Context& ctx) const
481 {
482 return new Maintenance3StructTestInstance(ctx);
483 }
484
485 private:
486 };
487
488 class Maintenance3DescriptorTestInstance : public TestInstance
489 {
490 public:
Maintenance3DescriptorTestInstance(Context & ctx)491 Maintenance3DescriptorTestInstance (Context& ctx)
492 : TestInstance(ctx)
493 {}
iterate(void)494 virtual tcu::TestStatus iterate (void)
495 {
496 const auto& vki = m_context.getInstanceInterface();
497 const auto& vkd = m_context.getDeviceInterface();
498 const auto& physicalDevice = m_context.getPhysicalDevice();
499 const auto& device = m_context.getDevice();
500 auto& log = m_context.getTestContext().getLog();
501 bool iubSupported = false;
502
503 if (m_context.isDeviceFunctionalitySupported("VK_EXT_inline_uniform_block"))
504 {
505 DevIubFeat iubFeatures =
506 {
507 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
508 DE_NULL,
509 0u,
510 0u
511 };
512
513 DevFeat2 features2 =
514 {
515 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
516 &iubFeatures,
517 VkPhysicalDeviceFeatures()
518 };
519
520 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
521 iubSupported = (iubFeatures.inlineUniformBlock == VK_TRUE);
522 }
523
524 DevIubProp devIubProp =
525 {
526 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT, // VkStructureType sType;
527 DE_NULL, // void* pNext;
528 0u, // deUint32 maxInlineUniformBlockSize;
529 0u, // deUint32 maxPerStageDescriptorInlineUniformBlocks;
530 0u, // deUint32 maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
531 0u, // deUint32 maxDescriptorSetInlineUniformBlocks;
532 0u // deUint32 maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
533 };
534
535 MaintDevProp3 maintProp3 =
536 {
537 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, //VkStructureType sType;
538 (iubSupported ? &devIubProp : DE_NULL), //void* pNext;
539 maxDescriptorsInSet, //deUint32 maxPerSetDescriptors;
540 maxMemoryAllocationSize //VkDeviceSize maxMemoryAllocationSize;
541 };
542
543 DevProp2 prop2 =
544 {
545 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, //VkStructureType sType;
546 &maintProp3, //void* pNext;
547 VkPhysicalDeviceProperties() //VkPhysicalDeviceProperties properties;
548 };
549
550 vki.getPhysicalDeviceProperties2(physicalDevice, &prop2);
551
552 vector<VkDescriptorType> descriptorTypes = {
553 VK_DESCRIPTOR_TYPE_SAMPLER,
554 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
555 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
556 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
557 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
558 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
559 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
560 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
561 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
562 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
563 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
564 };
565 if (iubSupported)
566 descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT);
567
568 // VkDescriptorSetLayoutCreateInfo setup
569 vk::VkDescriptorSetLayoutCreateInfo pCreateInfo =
570 {
571 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, //VkStructureType sType;
572 DE_NULL, //const void* pNext;
573 0u, //VkDescriptorSetLayoutCreateFlags flags;
574 0u, //deUint32 bindingCount;
575 DE_NULL //const VkDescriptorSetLayoutBinding* pBindings;
576 };
577
578 // VkDescriptorSetLayoutSupport setup
579 vk::VkDescriptorSetLayoutSupport pSupport =
580 {
581 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, //VkStructureType sType;
582 DE_NULL, //void* pNext;
583 VK_FALSE //VkBool32 supported;
584 };
585
586 // Check every combination maximizing descriptor counts.
587 for (size_t combSize = 1; combSize <= descriptorTypes.size(); ++combSize)
588 {
589 // Create a vector of selectors with combSize elements set to true.
590 vector<bool> selectors(descriptorTypes.size(), false);
591 std::fill(begin(selectors), begin(selectors) + combSize, true);
592
593 // Iterate over every permutation of selectors for that combination size.
594 do
595 {
596 vector<vk::VkDescriptorType> types;
597 for (size_t i = 0; i < selectors.size(); ++i)
598 {
599 if (selectors[i])
600 types.push_back(descriptorTypes[i]);
601 }
602
603 // Due to inline uniform blocks being unable to form arrays and each one of them needing its own
604 // VkDescriptorSetLayoutBinding structure, we will limit when to test them.
605 if (std::find(begin(types), end(types), VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) != types.end() &&
606 devIubProp.maxPerStageDescriptorInlineUniformBlocks > maxReasonableInlineUniformBlocks &&
607 combSize > 1u && combSize < descriptorTypes.size())
608 {
609 continue;
610 }
611
612 vector<vk::VkDescriptorSetLayoutBinding> bindings = calculateBindings(prop2.properties, devIubProp, maintProp3, types);
613
614 string description = getBindingsDescription(bindings);
615 log << tcu::TestLog::Message << "Testing combination: " << description << tcu::TestLog::EndMessage;
616
617 pCreateInfo.bindingCount = static_cast<deUint32>(bindings.size());
618 pCreateInfo.pBindings = bindings.data();
619
620 vkd.getDescriptorSetLayoutSupport(device, &pCreateInfo, &pSupport);
621 if (pSupport.supported == VK_FALSE)
622 {
623 ostringstream msg;
624 msg << "Failed to use the following descriptor type counts: " << description;
625 return tcu::TestStatus::fail(msg.str());
626 }
627 } while (std::prev_permutation(begin(selectors), end(selectors)));
628 }
629
630 return tcu::TestStatus::pass("Pass");
631 }
632
633 };
634
635 class Maintenance3DescriptorTestCase : public TestCase
636 {
637
638 public:
Maintenance3DescriptorTestCase(tcu::TestContext & testCtx)639 Maintenance3DescriptorTestCase (tcu::TestContext& testCtx)
640 : TestCase(testCtx, "descriptor_set", "tests vkGetDescriptorSetLayoutSupport struct")
641 {}
~Maintenance3DescriptorTestCase(void)642 virtual ~Maintenance3DescriptorTestCase (void)
643 {}
checkSupport(Context & ctx) const644 virtual void checkSupport (Context& ctx) const
645 {
646 ctx.requireDeviceFunctionality("VK_KHR_maintenance3");
647 }
createInstance(Context & ctx) const648 virtual TestInstance* createInstance (Context& ctx) const
649 {
650 return new Maintenance3DescriptorTestInstance(ctx);
651 }
652 };
653
654 } // anonymous
655
createMaintenance3Tests(tcu::TestContext & testCtx)656 tcu::TestCaseGroup* createMaintenance3Tests (tcu::TestContext& testCtx)
657 {
658 de::MovePtr<tcu::TestCaseGroup> main3Tests(new tcu::TestCaseGroup(testCtx, "maintenance3_check", "Maintenance3 Tests"));
659 main3Tests->addChild(new Maintenance3StructTestCase(testCtx));
660 main3Tests->addChild(new Maintenance3DescriptorTestCase(testCtx));
661
662 return main3Tests.release();
663 }
664
665 } // api
666 } // vkt
667