Relax protected heap allocation tests - continuation
authorTomasz Gregorek <t.gregorek@partner.samsung.com>
Fri, 29 Oct 2021 08:01:54 +0000 (03:01 -0500)
committerMatthew Netsch <quic_mnetsch@quicinc.com>
Fri, 3 Dec 2021 16:50:14 +0000 (11:50 -0500)
Some implementations have limitations on protected heap
allocations, and these limitations cannot be queried
using the Vulkan API. This change allows an out-of-memory
to happen after a certain number of allocations to
compensate that.

Fix protected memory allocation to be done on small
allocation chunks and ignore allocation failures
if there is at least 80 of concurrent allocations
at a time.

VK-GL-CTS issue: 3257

Affects:
dEQP-VK.memory.allocation.random.*

Components: Vulkan
Change-Id: I32ed020195ff468de468bbd8527dec1d7f0db183

external/vulkancts/modules/vulkan/memory/vktMemoryAllocationTests.cpp

index c1f5211..fd134fb 100644 (file)
@@ -535,8 +535,9 @@ struct MemoryType
 
 struct MemoryObject
 {
-       VkDeviceMemory  memory;
-       VkDeviceSize    size;
+       VkDeviceMemory                  memory;
+       VkDeviceSize                    size;
+       VkMemoryPropertyFlags   propertyFlags;
 };
 
 struct Heap
@@ -563,6 +564,7 @@ private:
        const deUint32                          m_totalDeviceMaskCombinations;
 
        deUint32                                        m_memoryObjectCount;
+       deUint32                                        m_memoryProtectedObjectCount;
        deUint32                                        m_currentDeviceMask;
        size_t                                          m_opNdx;
        de::Random                                      m_rng;
@@ -579,6 +581,7 @@ RandomAllocFreeTestInstance::RandomAllocFreeTestInstance (Context& context, Test
        , m_memoryLimits                                (getMemoryLimits(context.getTestContext().getPlatform().getVulkanPlatform()))
        , m_totalDeviceMaskCombinations (m_subsetAllocationAllowed ? (1 << m_numPhysDevices) - 1 : 1)
        , m_memoryObjectCount                   (0)
+       , m_memoryProtectedObjectCount  (0)
        , m_currentDeviceMask                   (m_subsetAllocationAllowed ? 1 : (1 << m_numPhysDevices) - 1)
        , m_opNdx                                               (0)
        , m_rng                                                 (config.seed)
@@ -706,10 +709,20 @@ tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
                Heap&                           heap                    = m_heaps[heapNdx];
                const MemoryType&       memoryType              = m_rng.choose<MemoryType>(heap.types.begin(), heap.types.end());
                const bool                      isDeviceLocal   = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
-               const VkDeviceSize      maxAllocSize    = (isDeviceLocal && !isUMA)
+               const bool                      isProtected             = memoryType.type.propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT;
+               VkDeviceSize            maxAllocSize    = (isDeviceLocal && !isUMA)
                                                                                        ? de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalDeviceLocalMemory - m_totalDeviceMem)
                                                                                        : de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalSystemMemory - usedSysMem - m_allocSysMemSize);
-               const VkDeviceSize      allocationSize  = 1 + (m_rng.getUint64() % maxAllocSize);
+               const VkDeviceSize      maxProtectedAllocSize = 1 * 1024 * 1024;
+
+               // Some implementations might have limitations on protected heap, and these
+               // limitations don't show up in Vulkan queries. Use a hard coded limit for
+               // allocations of arbitrarily selected size of 1MB as per Note at "Device
+               // Memory Allocation" at the spec to use minimum-size allocations.
+               if(isProtected)
+                       maxAllocSize = (maxAllocSize > maxProtectedAllocSize) ? maxProtectedAllocSize : maxAllocSize;
+
+               const VkDeviceSize allocationSize = 1 + (m_rng.getUint64() % maxAllocSize);
 
                if ((allocationSize > (deUint64)(heap.maxMemoryUsage - heap.memoryUsage)) && (allocationSize != 1))
                        TCU_THROW(InternalError, "Test Error: trying to allocate memory more than the available heap size.");
@@ -717,7 +730,8 @@ tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
                const MemoryObject object =
                {
                        (VkDeviceMemory)0,
-                       allocationSize
+                       allocationSize,
+                       memoryType.type.propertyFlags
                };
 
                heap.objects.push_back(object);
@@ -731,13 +745,30 @@ tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
                        memoryType.index                                                                        // memoryTypeIndex;
                };
 
-               VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory));
-               TCU_CHECK(!!heap.objects.back().memory);
-               m_memoryObjectCount++;
+               VkResult        res     = vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory);
+
+               // Some implementations might have limitations on protected heap, and these
+               // limitations don't show up in Vulkan queries. Use a hard coded threshold
+               // after which out of memory is allowed as per Note at "Device Memory Allocation"
+               // at the spec to support at least 80 allocations concurrently.
+               if (res == VK_ERROR_OUT_OF_DEVICE_MEMORY && isProtected && m_memoryProtectedObjectCount > 80)
+               {
+                       heap.objects.pop_back();
+               }
+               else
+               {
+                       VK_CHECK(res);
+
+                       TCU_CHECK(!!heap.objects.back().memory);
+                       m_memoryObjectCount++;
+
+                       if (isProtected)
+                               m_memoryProtectedObjectCount++;
 
-               heap.memoryUsage                                                                                += allocationSize;
-               (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem)   += allocationSize;
-               m_totalSystemMem                                                                                += m_allocSysMemSize;
+                       heap.memoryUsage                                                                                += allocationSize;
+                       (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem)   += allocationSize;
+                       m_totalSystemMem                                                                                += m_allocSysMemSize;
+               }
        }
        else
        {
@@ -749,9 +780,16 @@ tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
                const bool                      isDeviceLocal   = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
 
                vkd.freeMemory(device, memoryObject.memory, (const VkAllocationCallbacks*)DE_NULL);
+
                memoryObject.memory = (VkDeviceMemory)0;
                m_memoryObjectCount--;
 
+               if (memoryObject.propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT)
+               {
+                       m_memoryProtectedObjectCount--;
+                       memoryObject.propertyFlags = (VkMemoryPropertyFlags)0;
+               }
+
                heap.memoryUsage                                                                                -= memoryObject.size;
                (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem)   -= memoryObject.size;
                m_totalSystemMem                                                                                -= m_allocSysMemSize;