#include "vktApiMaintenance3Check.hpp"
#include "vktTestCase.hpp"
-#define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
+#include <sstream>
+#include <limits>
+#include <utility>
+#include <algorithm>
+#include <map>
+#include <set>
using namespace vk;
{
using ::std::string;
using ::std::vector;
+using ::std::map;
+using ::std::set;
+using ::std::ostringstream;
+using ::std::make_pair;
+
+typedef vk::VkPhysicalDeviceProperties DevProp1;
+typedef vk::VkPhysicalDeviceProperties2 DevProp2;
+typedef vk::VkPhysicalDeviceMaintenance3Properties MaintDevProp3;
+typedef vk::VkPhysicalDeviceFeatures2 DevFeat2;
+typedef vk::VkPhysicalDeviceInlineUniformBlockFeaturesEXT DevIubFeat;
+typedef vk::VkPhysicalDeviceInlineUniformBlockPropertiesEXT DevIubProp;
+
+// These variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
+constexpr deUint32 maxMemoryAllocationSize = 1073741824u;
+constexpr deUint32 maxDescriptorsInSet = 1024u;
+constexpr deUint32 maxReasonableInlineUniformBlocks = 64u;
+
+using TypeSet = set<vk::VkDescriptorType>;
+
+// Structure representing an implementation limit, like maxPerStageDescriptorSamplers. It has a maximum value
+// obtained at runtime and a remaining number of descriptors, which starts with the same count and decreases
+// as we assign descriptor counts to the different types. A limit is affected by (or itself affects) one or more
+// descriptor types. Note a type may be involved in several limits, and a limit may affect several types.
+struct Limit
+{
+ Limit(const string& name_, deUint32 maxValue_, const TypeSet& affectedTypes_)
+ : name(name_), maxValue(maxValue_), remaining(maxValue_), affectedTypes(affectedTypes_)
+ {}
+
+ const string name;
+ const deUint32 maxValue;
+ deUint32 remaining;
+ const TypeSet affectedTypes;
+};
+
+// Structure representing how many descriptors have been assigned to the given type. The type is "alive" during
+// descriptor count assignment if more descriptors can be added to the type without hitting any limit affected
+// by the type. Once at least one of the limits is reached, no more descriptors can be assigned to the type and
+// the type is no longer considered "alive".
+struct TypeState
+{
+ TypeState(vk::VkDescriptorType type_)
+ : type(type_), alive(true), count(0u)
+ {}
+
+ const vk::VkDescriptorType type;
+ bool alive;
+ deUint32 count;
+};
+
+using TypeCounts = map<vk::VkDescriptorType, TypeState>;
+using LimitsVector = vector<Limit>;
+
+// Get the subset of alive types from the given map.
+TypeSet getAliveTypes (const TypeCounts& typeCounts)
+{
+ TypeSet aliveTypes;
+ for (const auto& typeCount : typeCounts)
+ {
+ if (typeCount.second.alive)
+ aliveTypes.insert(typeCount.first);
+ }
+ return aliveTypes;
+}
+
+// Get the subset of alive types for a specific limit, among the set of types affected by the limit.
+TypeSet getAliveTypesForLimit (const Limit& limit, const TypeSet& aliveTypes)
+{
+ TypeSet subset;
+ for (const auto& type : limit.affectedTypes)
+ {
+ if (aliveTypes.find(type) != aliveTypes.end())
+ subset.insert(type);
+ }
+ return subset;
+}
+
+// Distribute descriptor counts as evenly as possible among the given set of types, taking into account the
+// given limits.
+void distributeCounts (LimitsVector& limits, TypeCounts& typeCounts)
+{
+ using IncrementsMap = map<vk::VkDescriptorType, deUint32>;
+ TypeSet aliveTypes;
+
+ while ((aliveTypes = getAliveTypes(typeCounts)).size() > 0u)
+ {
+ // Calculate the maximum increment per alive descriptor type. This involves iterating over the limits and
+ // finding out how many more descriptors can be distributed among the affected types that are still alive
+ // for the limit. For each type, remember the lowest possible increment.
+ IncrementsMap increments;
+ for (const auto& type : aliveTypes)
+ increments[type] = std::numeric_limits<deUint32>::max();
+
+ TypeSet aliveTypesForLimit;
+
+ for (const auto& limit : limits)
+ {
+ if (limit.remaining == 0u)
+ continue;
+
+ aliveTypesForLimit = getAliveTypesForLimit(limit, aliveTypes);
+ if (aliveTypesForLimit.empty())
+ continue;
+
+ // Distribute remaining count evenly among alive types.
+ deUint32 maxIncrement = limit.remaining / static_cast<deUint32>(aliveTypesForLimit.size());
+ if (maxIncrement == 0u)
+ {
+ // More types than remaining descriptors. Assign 1 to the first affected types and 0 to the rest.
+ deUint32 remaining = limit.remaining;
+ for (const auto& type : aliveTypesForLimit)
+ {
+ if (remaining > 0u && increments[type] > 0u)
+ {
+ increments[type] = 1u;
+ --remaining;
+ }
+ else
+ {
+ increments[type] = 0u;
+ }
+ }
+ }
+ else
+ {
+ // Find the lowest possible increment taking into account all limits.
+ for (const auto& type : aliveTypesForLimit)
+ {
+ if (increments[type] > maxIncrement)
+ increments[type] = maxIncrement;
+ }
+ }
+ }
+
+ // Apply the calculated increments per descriptor type, decreasing the remaining descriptors for each
+ // limit affected by the type, and switching types to the not-alive state when a limit is hit.
+ for (const auto& inc : increments)
+ {
+ const vk::VkDescriptorType& type = inc.first;
+ const deUint32& increment = inc.second;
+
+ // Increase type count.
+ auto iter = typeCounts.find(type);
+ DE_ASSERT(iter != typeCounts.end());
+ iter->second.count += increment;
+
+ for (auto& limit : limits)
+ {
+ // Decrease remaining descriptors for affected limits.
+ if (limit.affectedTypes.find(type) != limit.affectedTypes.end())
+ {
+ DE_ASSERT(increment <= limit.remaining);
+ limit.remaining -= increment;
+ }
+ if (limit.remaining == 0u)
+ {
+ // Limit hit, switch affected types to not-alive.
+ for (const auto& affectedType : limit.affectedTypes)
+ {
+ auto tc = typeCounts.find(affectedType);
+ if (tc != typeCounts.end())
+ tc->second.alive = false;
+ }
+ }
+ }
+ }
+ }
+}
+
+// Create a limits vector based on runtime limit information for the device.
+LimitsVector buildLimitsVector (const DevProp1& prop1, const DevIubProp& iubProp, const MaintDevProp3& maintProp3)
+{
+ static const TypeSet samplerTypes = { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_DESCRIPTOR_TYPE_SAMPLER };
+ static const TypeSet sampledImageTypes = { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER };
+ static const TypeSet uniformBufferTypes = { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC };
+ static const TypeSet storageBufferTypes = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC };
+ static const TypeSet storageImageTypes = { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER };
+ static const TypeSet inputAttachmentTypes = { vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT };
+ static const TypeSet inlineUniformBlockTypes = { vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT };
+ static const TypeSet dynamicUniformBuffer = { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC };
+ static const TypeSet dynamicStorageBuffer = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC };
+ static const TypeSet allTypesButIUB = {
+ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
+ vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ };
+ static const TypeSet allTypes = {
+ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ vk::VK_DESCRIPTOR_TYPE_SAMPLER,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
+ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT,
+ };
+
+ LimitsVector limits = {
+ {
+ "maxPerStageDescriptorSamplers",
+ prop1.limits.maxPerStageDescriptorSamplers,
+ samplerTypes
+ },
+ {
+ "maxDescriptorSetSamplers",
+ prop1.limits.maxDescriptorSetSamplers,
+ samplerTypes
+ },
+ {
+ "maxPerStageDescriptorSampledImages",
+ prop1.limits.maxPerStageDescriptorSampledImages,
+ sampledImageTypes
+ },
+ {
+ "maxDescriptorSetSampledImages",
+ prop1.limits.maxDescriptorSetSampledImages,
+ sampledImageTypes
+ },
+ {
+ "maxPerStageDescriptorUniformBuffers",
+ prop1.limits.maxPerStageDescriptorUniformBuffers,
+ uniformBufferTypes
+ },
+ {
+ "maxDescriptorSetUniformBuffers",
+ prop1.limits.maxDescriptorSetUniformBuffers,
+ uniformBufferTypes
+ },
+ {
+ "maxPerStageDescriptorStorageBuffers",
+ prop1.limits.maxPerStageDescriptorStorageBuffers,
+ storageBufferTypes
+ },
+ {
+ "maxDescriptorSetStorageBuffers",
+ prop1.limits.maxDescriptorSetStorageBuffers,
+ storageBufferTypes
+ },
+ {
+ "maxPerStageDescriptorStorageImages",
+ prop1.limits.maxPerStageDescriptorStorageImages,
+ storageImageTypes
+ },
+ {
+ "maxDescriptorSetStorageImages",
+ prop1.limits.maxDescriptorSetStorageImages,
+ storageImageTypes
+ },
+ {
+ "maxPerStageDescriptorInputAttachments",
+ prop1.limits.maxPerStageDescriptorInputAttachments,
+ inputAttachmentTypes
+ },
+ {
+ "maxDescriptorSetInputAttachments",
+ prop1.limits.maxDescriptorSetInputAttachments,
+ inputAttachmentTypes
+ },
+ {
+ "maxDescriptorSetUniformBuffersDynamic",
+ prop1.limits.maxDescriptorSetUniformBuffersDynamic,
+ dynamicUniformBuffer
+ },
+ {
+ "maxDescriptorSetStorageBuffersDynamic",
+ prop1.limits.maxDescriptorSetStorageBuffersDynamic,
+ dynamicStorageBuffer
+ },
+ {
+ "maxPerStageDescriptorInlineUniformBlocks",
+ iubProp.maxPerStageDescriptorInlineUniformBlocks,
+ inlineUniformBlockTypes
+ },
+ {
+ "maxDescriptorSetInlineUniformBlocks",
+ iubProp.maxDescriptorSetInlineUniformBlocks,
+ inlineUniformBlockTypes
+ },
+ {
+ "maxPerStageResources",
+ prop1.limits.maxPerStageResources,
+ allTypesButIUB
+ },
+ {
+ "maxPerSetDescriptors",
+ maintProp3.maxPerSetDescriptors,
+ allTypes
+ },
+ };
+
+ return limits;
+}
-typedef vk::VkPhysicalDeviceProperties DevProp1;
-typedef vk::VkPhysicalDeviceProperties2 DevProp2;
-typedef vk::VkPhysicalDeviceMaintenance3Properties MainDevProp3;
+// Create a vector of bindings by constructing the system limits and distributing descriptor counts.
+vector<vk::VkDescriptorSetLayoutBinding> calculateBindings(const DevProp1& prop1, const DevIubProp& iubProp, const MaintDevProp3& maintProp3, const vector<vk::VkDescriptorType> &types)
+{
+ LimitsVector limits = buildLimitsVector(prop1, iubProp, maintProp3);
+ TypeCounts typeCounts;
+
+ for (const auto& type : types)
+ typeCounts.emplace(make_pair(type, TypeState(type)));
+
+ distributeCounts(limits, typeCounts);
+
+ deUint32 bindingNumber = 0u;
+ vector<vk::VkDescriptorSetLayoutBinding> bindings;
+ for (const auto& tc : typeCounts)
+ {
+ if (tc.first != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
+ {
+ vk::VkDescriptorSetLayoutBinding b;
+ b.binding = bindingNumber;
+ b.descriptorCount = tc.second.count;
+ b.descriptorType = tc.first;
+ b.pImmutableSamplers = DE_NULL;
+ b.stageFlags = vk::VK_SHADER_STAGE_ALL;
+
+ bindings.push_back(b);
+ }
+ else
+ {
+ // Inline uniform blocks are special because descriptorCount represents the size of that block.
+ // The only way of creating several blocks is by adding more structures to the list instead of creating an array.
+ size_t firstAdded = bindings.size();
+ bindings.resize(firstAdded + tc.second.count);
+ for (deUint32 i = 0u; i < tc.second.count; ++i)
+ {
+ vk::VkDescriptorSetLayoutBinding& b = bindings[firstAdded + i];
+ b.binding = bindingNumber + i;
+ b.descriptorCount = 4u; // For inline uniform blocks, this must be a multiple of 4 according to the spec.
+ b.descriptorType = tc.first;
+ b.pImmutableSamplers = DE_NULL;
+ b.stageFlags = vk::VK_SHADER_STAGE_ALL;
+ }
+ }
+ bindingNumber += tc.second.count;
+ }
+
+ return bindings;
+}
+
+// Get a textual description with descriptor counts per type.
+string getBindingsDescription (const vector<VkDescriptorSetLayoutBinding>& bindings)
+{
+ map<vk::VkDescriptorType, deUint32> typeCount;
+ deUint32 totalCount = 0u;
+ deUint32 count;
+ for (const auto& b : bindings)
+ {
+ auto iter = typeCount.find(b.descriptorType);
+ if (iter == typeCount.end())
+ iter = typeCount.insert(make_pair(b.descriptorType, (deUint32)0)).first;
+ count = ((b.descriptorType == vk::VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1u : b.descriptorCount);
+ iter->second += count;
+ totalCount += count;
+ }
+
+ deUint32 i = 0;
+ ostringstream combStr;
+
+ combStr << "{ Descriptors: " << totalCount << ", [";
+ for (const auto& tc : typeCount)
+ combStr << (i++ ? ", " : " ") << tc.first << ": " << tc.second;
+ combStr << " ] }";
+
+ return combStr.str();
+}
class Maintenance3StructTestInstance : public TestInstance
{
{
tcu::TestLog& log = m_context.getTestContext().getLog();
- // these variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
- const deUint32 maxMemoryAllocationSize = 1073741824u;
- const deUint32 maxDescriptorsInSet = 1024u;
-
// set values to be a bit smaller than required minimum values
- MainDevProp3 mainProp3 =
+ MaintDevProp3 maintProp3 =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, //VkStructureType sType;
DE_NULL, //void* pNext;
DevProp2 prop2;
deMemset(&prop2, 0, sizeof(prop2)); // zero the structure
prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- prop2.pNext = &mainProp3;
+ prop2.pNext = &maintProp3;
m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &prop2);
- if (mainProp3.maxMemoryAllocationSize < maxMemoryAllocationSize)
+ if (maintProp3.maxMemoryAllocationSize < maxMemoryAllocationSize)
return tcu::TestStatus::fail("Fail");
- if (mainProp3.maxPerSetDescriptors < maxDescriptorsInSet)
+ if (maintProp3.maxPerSetDescriptors < maxDescriptorsInSet)
return tcu::TestStatus::fail("Fail");
- log << tcu::TestLog::Message << "maxMemoryAllocationSize: " << mainProp3.maxMemoryAllocationSize << tcu::TestLog::EndMessage;
- log << tcu::TestLog::Message << "maxPerSetDescriptors: " << mainProp3.maxPerSetDescriptors << tcu::TestLog::EndMessage;
+ log << tcu::TestLog::Message << "maxMemoryAllocationSize: " << maintProp3.maxMemoryAllocationSize << tcu::TestLog::EndMessage;
+ log << tcu::TestLog::Message << "maxPerSetDescriptors: " << maintProp3.maxPerSetDescriptors << tcu::TestLog::EndMessage;
return tcu::TestStatus::pass("Pass");
}
};
{}
virtual tcu::TestStatus iterate (void)
{
- // these variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
- const deUint32 maxMemoryAllocationSize = 1073741824u;
- const deUint32 maxDescriptorsInSet = 1024u;
+ const auto& vki = m_context.getInstanceInterface();
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto& physicalDevice = m_context.getPhysicalDevice();
+ const auto& device = m_context.getDevice();
+ auto& log = m_context.getTestContext().getLog();
+ bool iubSupported = false;
+ bool iubExtSupported = isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_EXT_inline_uniform_block");
+
+ if (iubExtSupported)
+ {
+ DevIubFeat iubFeatures =
+ {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
+ DE_NULL,
+ 0u,
+ 0u
+ };
+
+ DevFeat2 features2 =
+ {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ &iubFeatures,
+ VkPhysicalDeviceFeatures()
+ };
+
+ vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
+ iubSupported = (iubFeatures.inlineUniformBlock == VK_TRUE);
+ }
+
+ DevIubProp devIubProp =
+ {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT, // VkStructureType sType;
+ DE_NULL, // void* pNext;
+ 0u, // deUint32 maxInlineUniformBlockSize;
+ 0u, // deUint32 maxPerStageDescriptorInlineUniformBlocks;
+ 0u, // deUint32 maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+ 0u, // deUint32 maxDescriptorSetInlineUniformBlocks;
+ 0u // deUint32 maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+ };
- MainDevProp3 mainProp3 =
+ MaintDevProp3 maintProp3 =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, //VkStructureType sType;
- DE_NULL, //void* pNext;
+ (iubSupported ? &devIubProp : DE_NULL), //void* pNext;
maxDescriptorsInSet, //deUint32 maxPerSetDescriptors;
maxMemoryAllocationSize //VkDeviceSize maxMemoryAllocationSize;
};
DevProp2 prop2 =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, //VkStructureType sType;
- &mainProp3, //void* pNext;
+ &maintProp3, //void* pNext;
VkPhysicalDeviceProperties() //VkPhysicalDeviceProperties properties;
};
- DevProp1 prop1;
-
- m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &prop1);
- m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &prop2);
-
- // setup for descriptors sets
- VkDescriptorSetLayoutBinding descriptorSetLayoutBinding[VK_DESCRIPTOR_TYPE_LAST];
-
- for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
- {
- descriptorSetLayoutBinding[ndx].binding = ndx;
- descriptorSetLayoutBinding[ndx].descriptorType = static_cast<VkDescriptorType>(ndx);
- descriptorSetLayoutBinding[ndx].descriptorCount = mainProp3.maxPerSetDescriptors;
- descriptorSetLayoutBinding[ndx].stageFlags = VK_SHADER_STAGE_ALL;
- descriptorSetLayoutBinding[ndx].pImmutableSamplers = DE_NULL;
- }
+ vki.getPhysicalDeviceProperties2(physicalDevice, &prop2);
+
+ vector<VkDescriptorType> descriptorTypes = {
+ VK_DESCRIPTOR_TYPE_SAMPLER,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
+ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ };
+ if (iubSupported)
+ descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT);
// VkDescriptorSetLayoutCreateInfo setup
vk::VkDescriptorSetLayoutCreateInfo pCreateInfo =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, //VkStructureType sType;
DE_NULL, //const void* pNext;
0u, //VkDescriptorSetLayoutCreateFlags flags;
- 1u, //deUint32 bindingCount;
+ 0u, //deUint32 bindingCount;
DE_NULL //const VkDescriptorSetLayoutBinding* pBindings;
};
VK_FALSE //VkBool32 supported;
};
- // check for single descriptors
- for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
+ // Check every combination maximizing descriptor counts.
+ for (size_t combSize = 1; combSize <= descriptorTypes.size(); ++combSize)
{
- pCreateInfo.pBindings = &descriptorSetLayoutBinding[ndx];
- m_context.getDeviceInterface().getDescriptorSetLayoutSupport(m_context.getDevice(), &pCreateInfo, &pSupport);
+ // Create a vector of selectors with combSize elements set to true.
+ vector<bool> selectors(descriptorTypes.size(), false);
+ std::fill(begin(selectors), begin(selectors) + combSize, true);
- if(extraLimitCheck(descriptorSetLayoutBinding, ndx, pCreateInfo.bindingCount, prop1))
+ // Iterate over every permutation of selectors for that combination size.
+ do
{
+ vector<vk::VkDescriptorType> types;
+ for (size_t i = 0; i < selectors.size(); ++i)
+ {
+ if (selectors[i])
+ types.push_back(descriptorTypes[i]);
+ }
+
+ // Due to inline uniform blocks being unable to form arrays and each one of them needing its own
+ // VkDescriptorSetLayoutBinding structure, we will limit when to test them.
+ if (std::find(begin(types), end(types), VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) != types.end() &&
+ devIubProp.maxPerStageDescriptorInlineUniformBlocks > maxReasonableInlineUniformBlocks &&
+ combSize > 1u && combSize < descriptorTypes.size())
+ {
+ continue;
+ }
+
+ vector<vk::VkDescriptorSetLayoutBinding> bindings = calculateBindings(prop2.properties, devIubProp, maintProp3, types);
+
+ string description = getBindingsDescription(bindings);
+ log << tcu::TestLog::Message << "Testing combination: " << description << tcu::TestLog::EndMessage;
+
+ pCreateInfo.bindingCount = static_cast<deUint32>(bindings.size());
+ pCreateInfo.pBindings = bindings.data();
+
+ vkd.getDescriptorSetLayoutSupport(device, &pCreateInfo, &pSupport);
if (pSupport.supported == VK_FALSE)
- return tcu::TestStatus::fail("fail");
- }
- }
-
- // check for accumulated descriptors (all eleven types)
-
- pCreateInfo.pBindings = &descriptorSetLayoutBinding[0u];
- pCreateInfo.bindingCount = static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
-
- deUint32 fraction = mainProp3.maxPerSetDescriptors / static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
- deUint32 rest = mainProp3.maxPerSetDescriptors % static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
-
- for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
- descriptorSetLayoutBinding[ndx].descriptorCount = fraction;
- descriptorSetLayoutBinding[0u].descriptorCount += rest;
-
- m_context.getDeviceInterface().getDescriptorSetLayoutSupport(m_context.getDevice(), &pCreateInfo, &pSupport);
-
- if (extraLimitCheck(descriptorSetLayoutBinding, 0u, pCreateInfo.bindingCount, prop1))
- {
- if (pSupport.supported == VK_FALSE)
- return tcu::TestStatus::fail("fail");
+ {
+ ostringstream msg;
+ msg << "Failed to use the following descriptor type counts: " << description;
+ return tcu::TestStatus::fail(msg.str());
+ }
+ } while (std::prev_permutation(begin(selectors), end(selectors)));
}
return tcu::TestStatus::pass("Pass");
}
-private:
- bool extraLimitCheck (const VkDescriptorSetLayoutBinding* descriptorSetLayoutBinding, const deUint32& curNdx, const deUint32& size, const DevProp1& prop1)
- {
- deUint32 maxPerStageDescriptorSamplers = 0u;
- deUint32 maxPerStageDescriptorUniformBuffers = 0u;
- deUint32 maxPerStageDescriptorStorageBuffers = 0u;
- deUint32 maxPerStageDescriptorSampledImages = 0u;
- deUint32 maxPerStageDescriptorStorageImages = 0u;
- deUint32 maxPerStageDescriptorInputAttachments = 0u;
-
- for(deUint32 ndx = curNdx; ndx < curNdx + size; ++ndx)
- {
- if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
- maxPerStageDescriptorSamplers += descriptorSetLayoutBinding->descriptorCount;
-
- if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC))
- maxPerStageDescriptorUniformBuffers += descriptorSetLayoutBinding->descriptorCount;
-
- if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC))
- maxPerStageDescriptorStorageBuffers += descriptorSetLayoutBinding->descriptorCount;
-
- if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER))
- maxPerStageDescriptorSampledImages += descriptorSetLayoutBinding->descriptorCount;
-
- if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
- (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER))
- maxPerStageDescriptorStorageImages += descriptorSetLayoutBinding->descriptorCount;
-
- if (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
- maxPerStageDescriptorInputAttachments += descriptorSetLayoutBinding->descriptorCount;
- }
-
- if (prop1.limits.maxPerStageDescriptorSamplers < maxPerStageDescriptorSamplers)
- return false;
- if (prop1.limits.maxPerStageDescriptorUniformBuffers < maxPerStageDescriptorUniformBuffers)
- return false;
- if (prop1.limits.maxPerStageDescriptorStorageBuffers < maxPerStageDescriptorStorageBuffers)
- return false;
- if (prop1.limits.maxPerStageDescriptorSampledImages < maxPerStageDescriptorSampledImages)
- return false;
- if (prop1.limits.maxPerStageDescriptorStorageImages < maxPerStageDescriptorStorageImages)
- return false;
- if (prop1.limits.maxPerStageDescriptorInputAttachments < maxPerStageDescriptorInputAttachments)
- return false;
-
- return true;
- }
};
class Maintenance3DescriptorTestCase : public TestCase
{
return new Maintenance3DescriptorTestInstance(ctx);
}
-
-private:
};
} // anonymous
- tcu::TestCaseGroup* createMaintenance3Tests (tcu::TestContext& testCtx)
+tcu::TestCaseGroup* createMaintenance3Tests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> main3Tests(new tcu::TestCaseGroup(testCtx, "maintenance3_check", "Maintenance3 Tests"));
main3Tests->addChild(new Maintenance3StructTestCase(testCtx));