Optimize swapchain OOM tests
authorPyry Haulos <phaulos@google.com>
Wed, 4 Jan 2017 22:30:07 +0000 (14:30 -0800)
committerPyry Haulos <phaulos@google.com>
Mon, 9 Jan 2017 17:06:32 +0000 (09:06 -0800)
Swapchain OOM tests were hitting timeouts on some platforms. This commit
optimizes the tests in two ways:

 * VkInstance, VkDevice, and VkSurface are now re-used across all
sub-cases.

 * Loop is re-written to avoid re-creating swapchains for parameters
0..N-1 when testing parameter combination N.

Affects: dEQP-VK.wsi.*.swapchain.simulate_oom.*

Bug: 33555898
(cherry picked from commit 2beac9057d9113ac306632d819ded852691a6842)

Change-Id: I19e9c7c8012a82cd12322a733afab961f4c7a1ae

external/vulkancts/framework/vulkan/vkAllocationCallbackUtil.cpp
external/vulkancts/framework/vulkan/vkAllocationCallbackUtil.hpp
external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp
external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp
external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp

index 9569282..961b1c4 100644 (file)
@@ -277,21 +277,21 @@ void AllocationCallbackRecorder::notifyInternalFree (size_t size, VkInternalAllo
 
 // DeterministicFailAllocator
 
-DeterministicFailAllocator::DeterministicFailAllocator (const VkAllocationCallbacks* allocator, deUint32 numPassingAllocs, Mode initialMode)
+DeterministicFailAllocator::DeterministicFailAllocator (const VkAllocationCallbacks* allocator, Mode mode, deUint32 numPassingAllocs)
        : ChainedAllocator      (allocator)
-       , m_numPassingAllocs(numPassingAllocs)
-       , m_mode                        (initialMode)
-       , m_allocationNdx       (0)
 {
+       reset(mode, numPassingAllocs);
 }
 
 DeterministicFailAllocator::~DeterministicFailAllocator (void)
 {
 }
 
-void DeterministicFailAllocator::setMode (Mode mode)
+void DeterministicFailAllocator::reset (Mode mode, deUint32 numPassingAllocs)
 {
-       m_mode = mode;
+       m_mode                          = mode;
+       m_numPassingAllocs      = numPassingAllocs;
+       m_allocationNdx         = 0;
 }
 
 void* DeterministicFailAllocator::allocate (size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
index 63cabd8..407ea02 100644 (file)
@@ -166,18 +166,17 @@ public:
                MODE_LAST
        };
 
-                                                       DeterministicFailAllocator      (const VkAllocationCallbacks* allocator, deUint32 numPassingAllocs, Mode initialMode);
+                                                       DeterministicFailAllocator      (const VkAllocationCallbacks* allocator, Mode mode, deUint32 numPassingAllocs);
                                                        ~DeterministicFailAllocator     (void);
 
-       void                                    setMode                                         (Mode mode);
+       void                                    reset                                           (Mode mode, deUint32 numPassingAllocs);
 
        void*                                   allocate                                        (size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
        void*                                   reallocate                                      (void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
 
 private:
-       const deUint32                  m_numPassingAllocs;
-
        Mode                                    m_mode;
+       deUint32                                m_numPassingAllocs;
        volatile deUint32               m_allocationNdx;
 };
 
index 771f996..b72265e 100644 (file)
@@ -2325,8 +2325,8 @@ tcu::TestStatus allocCallbackFailTest (Context& context, typename Object::Parame
                for (; numPassingAllocs < maxTries; ++numPassingAllocs)
                {
                        DeterministicFailAllocator                      objAllocator(getSystemAllocator(),
-                                                                                                                        numPassingAllocs,
-                                                                                                                        DeterministicFailAllocator::MODE_COUNT_AND_FAIL);
+                                                                                                                        DeterministicFailAllocator::MODE_COUNT_AND_FAIL,
+                                                                                                                        numPassingAllocs);
                        AllocationCallbackRecorder                      recorder        (objAllocator.getCallbacks(), 128);
                        const Environment                                       objEnv          (resEnv.env.vkp,
                                                                                                                         resEnv.env.vkd,
index b74bda0..b12caa5 100644 (file)
@@ -231,8 +231,8 @@ tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
        {
                AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
                DeterministicFailAllocator      failingAllocator        (allocationRecorder.getCallbacks(),
-                                                                                                                numPassingAllocs,
-                                                                                                                DeterministicFailAllocator::MODE_DO_NOT_COUNT);
+                                                                                                                DeterministicFailAllocator::MODE_DO_NOT_COUNT,
+                                                                                                                0);
                bool                                            gotOOM                          = false;
 
                log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
@@ -243,7 +243,7 @@ tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
 
                        // OOM is not simulated for VkInstance as we don't want to spend time
                        // testing OOM paths inside instance creation.
-                       failingAllocator.setMode(DeterministicFailAllocator::MODE_COUNT_AND_FAIL);
+                       failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
 
                        const NativeObjects                     native          (context, instHelper.supportedExtensions, wsiType);
                        const Unique<VkSurfaceKHR>      surface         (createSurface(instHelper.vki,
index d18c88a..1d72fd3 100644 (file)
@@ -578,99 +578,84 @@ tcu::TestStatus createSwapchainTest (Context& context, TestParameters params)
        return tcu::TestStatus::pass("Creating swapchain succeeded");
 }
 
-class CreateSwapchainSimulateOOMTest : public TestInstance
+tcu::TestStatus createSwapchainSimulateOOMTest (Context& context, TestParameters params)
 {
-public:
-                                                       CreateSwapchainSimulateOOMTest  (Context& context, TestParameters params)
-                       : TestInstance                  (context)
-                       , m_params                              (params)
-                       , m_numPassingAllocs    (0)
-       {
-       }
-
-       tcu::TestStatus                 iterate                                                 (void);
-
-private:
-       const TestParameters    m_params;
-       deUint32                                m_numPassingAllocs;
-};
-
-tcu::TestStatus CreateSwapchainSimulateOOMTest::iterate (void)
-{
-       tcu::TestLog&   log     = m_context.getTestContext().getLog();
+       const size_t                            maxCases                        = 300u;
+       const deUint32                          maxAllocs                       = 1024u;
 
-       // \note This is a little counter-intuitive order (iterating on callback count until all cases pass)
-       //               but since cases depend on what device reports, it is the only easy way. In practice
-       //               we should see same number of total callbacks (and executed code) regardless of the
-       //               loop order.
+       tcu::TestLog&                           log                                     = context.getTestContext().getLog();
+       tcu::ResultCollector            results                         (log);
 
-       if (m_numPassingAllocs <= 16*1024u)
+       AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
+       DeterministicFailAllocator      failingAllocator        (allocationRecorder.getCallbacks(),
+                                                                                                        DeterministicFailAllocator::MODE_DO_NOT_COUNT,
+                                                                                                        0);
        {
-               AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
-               DeterministicFailAllocator      failingAllocator        (allocationRecorder.getCallbacks(),
-                                                                                                                m_numPassingAllocs,
-                                                                                                                DeterministicFailAllocator::MODE_DO_NOT_COUNT);
-               bool                                            gotOOM                          = false;
-
-               log << TestLog::Message << "Testing with " << m_numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
-
-               try
+               const InstanceHelper                                    instHelper      (context, params.wsiType, failingAllocator.getCallbacks());
+               const NativeObjects                                             native          (context, instHelper.supportedExtensions, params.wsiType);
+               const Unique<VkSurfaceKHR>                              surface         (createSurface(instHelper.vki,
+                                                                                                                                                       *instHelper.instance,
+                                                                                                                                                       params.wsiType,
+                                                                                                                                                       *native.display,
+                                                                                                                                                       *native.window,
+                                                                                                                                                       failingAllocator.getCallbacks()));
+               const DeviceHelper                                              devHelper       (context, instHelper.vki, *instHelper.instance, *surface, failingAllocator.getCallbacks());
+               const vector<VkSwapchainCreateInfoKHR>  allCases        (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
+
+               if (maxCases < allCases.size())
+                       log << TestLog::Message << "Note: Will only test first " << maxCases << " cases out of total of " << allCases.size() << " parameter combinations" << TestLog::EndMessage;
+
+               for (size_t caseNdx = 0; caseNdx < de::min(maxCases, allCases.size()); ++caseNdx)
                {
-                       const InstanceHelper                                    instHelper      (m_context, m_params.wsiType, failingAllocator.getCallbacks());
-                       const NativeObjects                                             native          (m_context, instHelper.supportedExtensions, m_params.wsiType);
-                       const Unique<VkSurfaceKHR>                              surface         (createSurface(instHelper.vki,
-                                                                                                                                                          *instHelper.instance,
-                                                                                                                                                          m_params.wsiType,
-                                                                                                                                                          *native.display,
-                                                                                                                                                          *native.window,
-                                                                                                                                                          failingAllocator.getCallbacks()));
-                       const DeviceHelper                                              devHelper       (m_context, instHelper.vki, *instHelper.instance, *surface, failingAllocator.getCallbacks());
-                       const vector<VkSwapchainCreateInfoKHR>  cases           (generateSwapchainParameterCases(m_params.wsiType, m_params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
-
-                       // We don't care testing OOM paths in VkInstance, VkSurface, or VkDevice
-                       // creation as they are tested elsewhere.
-                       failingAllocator.setMode(DeterministicFailAllocator::MODE_COUNT_AND_FAIL);
-
-                       for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+                       log << TestLog::Message << "Testing parameter case " << caseNdx << ": " << allCases[caseNdx] << TestLog::EndMessage;
+
+                       for (deUint32 numPassingAllocs = 0; numPassingAllocs <= maxAllocs; ++numPassingAllocs)
                        {
-                               VkSwapchainCreateInfoKHR        curParams       = cases[caseNdx];
+                               bool    gotOOM  = false;
 
-                               curParams.surface                               = *surface;
-                               curParams.queueFamilyIndexCount = 1u;
-                               curParams.pQueueFamilyIndices   = &devHelper.queueFamilyIndex;
+                               failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
 
-                               log
-                                       << TestLog::Message << "Sub-case " << (caseNdx+1) << " / " << cases.size() << TestLog::EndMessage;
+                               log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
 
+                               try
                                {
-                                       const Unique<VkSwapchainKHR>    swapchain       (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks()));
+                                       VkSwapchainCreateInfoKHR        curParams       = allCases[caseNdx];
+
+                                       curParams.surface                               = *surface;
+                                       curParams.queueFamilyIndexCount = 1u;
+                                       curParams.pQueueFamilyIndices   = &devHelper.queueFamilyIndex;
+
+                                       {
+                                               const Unique<VkSwapchainKHR>    swapchain       (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks()));
+                                       }
+                               }
+                               catch (const OutOfMemoryError& e)
+                               {
+                                       log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
+                                       gotOOM = true;
                                }
-                       }
-               }
-               catch (const OutOfMemoryError& e)
-               {
-                       log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
-                       gotOOM = true;
-               }
 
-               if (!validateAndLog(log, allocationRecorder, 0u))
-                       return tcu::TestStatus::fail("Detected invalid system allocation callback");
+                               if (!gotOOM)
+                               {
+                                       log << TestLog::Message << "Creating swapchain succeeded!" << TestLog::EndMessage;
 
-               if (!gotOOM)
-               {
-                       log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
+                                       if (numPassingAllocs == 0)
+                                               results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
 
-                       if (m_numPassingAllocs == 0)
-                               return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
-                       else
-                               return tcu::TestStatus::pass("OOM simulation completed");
+                                       break;
+                               }
+                               else if (numPassingAllocs == maxAllocs)
+                                       results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded");
+                       }
                }
 
-               m_numPassingAllocs++;
-               return tcu::TestStatus::incomplete();
+               context.getTestContext().touchWatchdog();
        }
-       else
-               return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded");
+
+       if (!validateAndLog(log, allocationRecorder, 0u))
+               results.fail("Detected invalid system allocation callback");
+
+       return tcu::TestStatus(results.getResult(), results.getMessage());
 }
 
 struct GroupParameters
@@ -701,16 +686,6 @@ void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters para
        }
 }
 
-void populateSwapchainOOMGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
-{
-       for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
-       {
-               const TestDimension             testDimension   = (TestDimension)dimensionNdx;
-
-               testGroup->addChild(new InstanceFactory1<CreateSwapchainSimulateOOMTest, TestParameters>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, getTestDimensionName(testDimension), "", TestParameters(wsiType, testDimension)));
-       }
-}
-
 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type                                             wsiType,
                                                                                                          const InstanceInterface&      vki,
                                                                                                          VkPhysicalDevice                      physicalDevice,
@@ -1701,7 +1676,7 @@ void populateModifyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
 void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
 {
        addTestGroup(testGroup, "create",                       "Create VkSwapchain with various parameters",                                   populateSwapchainGroup,         GroupParameters(wsiType, createSwapchainTest));
-       addTestGroup(testGroup, "simulate_oom",         "Simulate OOM using callbacks during swapchain construction",   populateSwapchainOOMGroup,      wsiType);
+       addTestGroup(testGroup, "simulate_oom",         "Simulate OOM using callbacks during swapchain construction",   populateSwapchainGroup,         GroupParameters(wsiType, createSwapchainSimulateOOMTest));
        addTestGroup(testGroup, "render",                       "Rendering Tests",                                                                                              populateRenderGroup,            wsiType);
        addTestGroup(testGroup, "modify",                       "Modify VkSwapchain",                                                                                   populateModifyGroup,            wsiType);
 }