Share instance/device across test case instances in dEQP-VK.synchronization.*
authorJeff Bolz <jbolz@nvidia.com>
Thu, 18 Jul 2019 19:45:02 +0000 (14:45 -0500)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 3 Oct 2019 18:07:58 +0000 (14:07 -0400)
Some of the dEQP-VK.synchronization.* test groups create new devices or new
instances for each test case. This is a really expensive thing to do tens of
thousands of times, and makes this the longest-running test group in the CTS.
This change uses singleton objects to store the instance/device, and adds
cleanup callbacks to destroy the singletons when the group is finished.

VK-GL-CTS Issue: 1886
Components: Vulkan
Affects: dEQP-VK.synchronization.*

Change-Id: If935b457276790faf4a86e6f2afb5fd911987a85
(cherry picked from commit 90e05499c49c88fc4063748574931c3be5652b07)

external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperationMultiQueueTests.cpp
external/vulkancts/modules/vulkan/synchronization/vktSynchronizationWin32KeyedMutexTests.cpp
external/vulkancts/modules/vulkan/vktTestGroupUtil.cpp
external/vulkancts/modules/vulkan/vktTestGroupUtil.hpp

index 13b54f3..5c2c3a5 100644 (file)
 #include "vkPlatform.hpp"
 #include "vkCmdUtil.hpp"
 #include "vktTestCaseUtil.hpp"
+#include "deSharedPtr.hpp"
 
 #include "vktSynchronizationUtil.hpp"
 #include "vktSynchronizationOperation.hpp"
 #include "vktSynchronizationOperationTestData.hpp"
 #include "vktSynchronizationOperationResources.hpp"
 #include "vktExternalMemoryUtil.hpp"
+#include "vktTestGroupUtil.hpp"
 
 #include "tcuResultCollector.hpp"
 #include "tcuTestLog.hpp"
@@ -46,6 +48,8 @@ namespace synchronization
 {
 namespace
 {
+using namespace vk;
+using de::SharedPtr;
 
 struct TestConfig
 {
@@ -397,50 +401,37 @@ vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, vk::Vk
        return (vk::VkPhysicalDevice)0;
 }
 
-vk::Move<vk::VkDevice> createDevice (const deUint32                                                                    apiVersion,
+vk::Move<vk::VkDevice> createDevice (const Context&            context,
                                                                         const vk::PlatformInterface&                                   vkp,
                                                                         vk::VkInstance                                                                 instance,
                                                                         const vk::InstanceInterface&                                   vki,
-                                                                        vk::VkPhysicalDevice                                                   physicalDevice,
-                                                                        vk::VkExternalMemoryHandleTypeFlagBits         memoryHandleType,
-                                                                        vk::VkExternalSemaphoreHandleTypeFlagBits      semaphoreHandleType,
-                                                                        bool                                                                                   dedicated,
-                                                                        bool                                                                               khrMemReqSupported)
+                                                                        const vk::VkPhysicalDevice                                             physicalDevice)
 {
        const float                                                                             priority                                = 0.0f;
        const std::vector<vk::VkQueueFamilyProperties>  queueFamilyProperties   = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
        std::vector<deUint32>                                                   queueFamilyIndices              (queueFamilyProperties.size(), 0xFFFFFFFFu);
        std::vector<const char*>                                                extensions;
 
-       if (dedicated)
-               if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
-                       extensions.push_back("VK_KHR_dedicated_allocation");
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_dedicated_allocation"))
+               extensions.push_back("VK_KHR_dedicated_allocation");
 
-       if (khrMemReqSupported)
-               if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
-                       extensions.push_back("VK_KHR_get_memory_requirements2");
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_get_memory_requirements2"))
+               extensions.push_back("VK_KHR_get_memory_requirements2");
 
-       if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_semaphore"))
                extensions.push_back("VK_KHR_external_semaphore");
-       if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_memory"))
                extensions.push_back("VK_KHR_external_memory");
 
-       if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
-               || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
-               || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
-       {
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_semaphore_fd"))
                extensions.push_back("VK_KHR_external_semaphore_fd");
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_memory_fd"))
                extensions.push_back("VK_KHR_external_memory_fd");
-       }
 
-       if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
-               || memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
-               || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
-               || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
-       {
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_semaphore_win32"))
                extensions.push_back("VK_KHR_external_semaphore_win32");
+       if (isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_external_memory_win32"))
                extensions.push_back("VK_KHR_external_memory_win32");
-       }
 
        try
        {
@@ -490,6 +481,63 @@ vk::Move<vk::VkDevice> createDevice (const deUint32                                                                        apiVersion,
        }
 }
 
+// Class to wrap a singleton instance and device
+class InstanceAndDevice
+{
+       InstanceAndDevice       (const Context& context)
+               : m_instance            (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
+               , m_vki                         (context.getPlatformInterface(), *m_instance)
+               , m_physicalDevice      (getPhysicalDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
+               , m_logicalDevice       (createDevice(context, context.getPlatformInterface(), *m_instance, m_vki, m_physicalDevice))
+       {
+       }
+
+public:
+
+       static const vk::Unique<vk::VkInstance>& getInstanceA(const Context& context)
+       {
+               if (!m_instanceA)
+                       m_instanceA = SharedPtr<InstanceAndDevice>(new InstanceAndDevice(context));
+
+               return m_instanceA->m_instance;
+       }
+       static const Unique<vk::VkInstance>& getInstanceB(const Context& context)
+       {
+               if (!m_instanceB)
+                       m_instanceB = SharedPtr<InstanceAndDevice>(new InstanceAndDevice(context));
+
+               return m_instanceB->m_instance;
+       }
+       static const Unique<vk::VkDevice>& getDeviceA()
+       {
+               DE_ASSERT(m_instanceA);
+               return m_instanceA->m_logicalDevice;
+       }
+       static const Unique<vk::VkDevice>& getDeviceB()
+       {
+               DE_ASSERT(m_instanceB);
+               return m_instanceB->m_logicalDevice;
+       }
+
+       static void destroy()
+       {
+               m_instanceA.clear();
+               m_instanceB.clear();
+       }
+
+private:
+       const Unique<vk::VkInstance>    m_instance;
+       const vk::InstanceDriver                m_vki;
+       const vk::VkPhysicalDevice              m_physicalDevice;
+       const Unique<vk::VkDevice>              m_logicalDevice;
+
+       static SharedPtr<InstanceAndDevice>     m_instanceA;
+       static SharedPtr<InstanceAndDevice>     m_instanceB;
+};
+SharedPtr<InstanceAndDevice>           InstanceAndDevice::m_instanceA;
+SharedPtr<InstanceAndDevice>           InstanceAndDevice::m_instanceB;
+
+
 vk::VkQueue getQueue (const vk::DeviceInterface&       vkd,
                                          const vk::VkDevice                    device,
                                          deUint32                                              familyIndex)
@@ -1003,7 +1051,7 @@ private:
        const de::UniquePtr<OperationSupport>                           m_supportReadOp;
        const NotSupportedChecker                                                       m_notSupportedChecker; // Must declare before VkInstance to effectively reduce runtimes!
 
-       const vk::Unique<vk::VkInstance>                                        m_instanceA;
+       const vk::Unique<vk::VkInstance>&                                       m_instanceA;
 
        const vk::InstanceDriver                                                        m_vkiA;
        const vk::VkPhysicalDevice                                                      m_physicalDeviceA;
@@ -1012,15 +1060,15 @@ private:
 
        const bool                                                                                      m_getMemReq2Supported;
 
-       const vk::Unique<vk::VkDevice>                                          m_deviceA;
+       const vk::Unique<vk::VkDevice>&                                         m_deviceA;
        const vk::DeviceDriver                                                          m_vkdA;
 
-       const vk::Unique<vk::VkInstance>                                        m_instanceB;
+       const vk::Unique<vk::VkInstance>&                                       m_instanceB;
        const vk::InstanceDriver                                                        m_vkiB;
        const vk::VkPhysicalDevice                                                      m_physicalDeviceB;
        const std::vector<vk::VkQueueFamilyProperties>          m_queueFamiliesB;
        const std::vector<deUint32>                                                     m_queueFamilyIndicesB;
-       const vk::Unique<vk::VkDevice>                                          m_deviceB;
+       const vk::Unique<vk::VkDevice>&                                         m_deviceB;
        const vk::DeviceDriver                                                          m_vkdB;
 
        const vk::VkExternalSemaphoreHandleTypeFlagBits m_semaphoreHandleType;
@@ -1041,23 +1089,23 @@ SharingTestInstance::SharingTestInstance (Context&              context,
        , m_supportReadOp                       (makeOperationSupport(config.readOp, config.resource))
        , m_notSupportedChecker         (context, m_config, *m_supportWriteOp, *m_supportReadOp)
 
-       , m_instanceA                           (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
+       , m_instanceA                           (InstanceAndDevice::getInstanceA(context))
 
        , m_vkiA                                        (context.getPlatformInterface(), *m_instanceA) // \todo [2017-06-13 pyry] Provide correct extension list
        , m_physicalDeviceA                     (getPhysicalDevice(m_vkiA, *m_instanceA, context.getTestContext().getCommandLine()))
        , m_queueFamiliesA                      (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA))
        , m_queueFamilyIndicesA         (getFamilyIndices(m_queueFamiliesA))
        , m_getMemReq2Supported         (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_get_memory_requirements2"))
-       , m_deviceA                                     (createDevice(context.getUsedApiVersion(), context.getPlatformInterface(), *m_instanceA, m_vkiA, m_physicalDeviceA, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
+       , m_deviceA                                     (InstanceAndDevice::getDeviceA())
        , m_vkdA                                        (context.getPlatformInterface(), *m_instanceA, *m_deviceA)
 
-       , m_instanceB                           (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
+       , m_instanceB                           (InstanceAndDevice::getInstanceB(context))
 
        , m_vkiB                                        (context.getPlatformInterface(), *m_instanceB) // \todo [2017-06-13 pyry] Provide correct extension list
        , m_physicalDeviceB                     (getPhysicalDevice(m_vkiB, *m_instanceB, getDeviceId(m_vkiA, m_physicalDeviceA)))
        , m_queueFamiliesB                      (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB))
        , m_queueFamilyIndicesB         (getFamilyIndices(m_queueFamiliesB))
-       , m_deviceB                                     (createDevice(context.getUsedApiVersion(), context.getPlatformInterface(), *m_instanceB, m_vkiB, m_physicalDeviceB, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
+       , m_deviceB                                     (InstanceAndDevice::getDeviceB())
        , m_vkdB                                        (context.getPlatformInterface(), *m_instanceB, *m_deviceB)
 
        , m_semaphoreHandleType         (m_config.semaphoreHandleType)
@@ -1296,8 +1344,9 @@ struct Progs
 
 } // anonymous
 
-tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
+static void createTests (tcu::TestCaseGroup* group)
 {
+       tcu::TestContext& testCtx = group->getTestContext();
        const struct
        {
                vk::VkExternalMemoryHandleTypeFlagBits          memoryType;
@@ -1326,7 +1375,6 @@ tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
                        "_win32"
                },
        };
-       de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
 
        for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
        {
@@ -1367,8 +1415,18 @@ tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
 
                group->addChild(dedicatedGroup.release());
        }
+}
 
-       return group.release();
+static void cleanupGroup (tcu::TestCaseGroup* group)
+{
+       DE_UNREF(group);
+       // Destroy singleton object
+       InstanceAndDevice::destroy();
+}
+
+tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
+{
+       return createTestGroup(testCtx, "cross_instance", "", createTests, cleanupGroup);
 }
 
 } // synchronization
index 8a292e7..96207d8 100644 (file)
@@ -34,6 +34,7 @@
 #include "vkPlatform.hpp"
 #include "vkCmdUtil.hpp"
 #include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
 #include "tcuTestLog.hpp"
 #include "vktSynchronizationUtil.hpp"
 #include "vktSynchronizationOperation.hpp"
@@ -50,6 +51,7 @@ namespace
 using namespace vk;
 using de::MovePtr;
 using de::UniquePtr;
+using de::SharedPtr;
 
 enum QueueType
 {
@@ -88,7 +90,6 @@ class MultiQueues
                std::vector<VkQueue>    queue;
        };
 
-public:
        MultiQueues     (const Context& context)
        {
                const InstanceInterface&                                        instance                                = context.getInstanceInterface();
@@ -152,13 +153,14 @@ public:
                m_queues[queueFamilyIndex] = dataToPush;
        }
 
-       std::vector<QueuePair> getQueuesPairs (const VkQueueFlags flagsWrite, const VkQueueFlags flagsRead)
+public:
+       std::vector<QueuePair> getQueuesPairs (const VkQueueFlags flagsWrite, const VkQueueFlags flagsRead) const
        {
                std::map<deUint32, QueueData>   queuesWrite;
                std::map<deUint32, QueueData>   queuesRead;
                std::vector<QueuePair>                  queuesPairs;
 
-               for (std::map<deUint32, QueueData>::iterator it = m_queues.begin(); it != m_queues.end(); ++it)
+               for (std::map<deUint32, QueueData>::const_iterator it = m_queues.begin(); it != m_queues.end(); ++it)
                {
                        const bool writeQueue   = checkQueueFlags(it->second.flags, flagsWrite);
                        const bool readQueue    = checkQueueFlags(it->second.flags, flagsRead);
@@ -215,12 +217,27 @@ public:
                return *m_allocator;
        }
 
+       static SharedPtr<MultiQueues> getInstance(const Context& context)
+       {
+               if (!m_multiQueues)
+                       m_multiQueues = SharedPtr<MultiQueues>(new MultiQueues(context));
+
+               return m_multiQueues;
+       }
+       static void destroy()
+       {
+               m_multiQueues.clear();
+       }
+
 private:
        Move<VkDevice>                                  m_logicalDevice;
        MovePtr<DeviceDriver>                   m_deviceDriver;
        MovePtr<Allocator>                              m_allocator;
        std::map<deUint32, QueueData>   m_queues;
+
+       static SharedPtr<MultiQueues>   m_multiQueues;
 };
+SharedPtr<MultiQueues>                         MultiQueues::m_multiQueues;
 
 void createBarrierMultiQueue (const DeviceInterface&   vk,
                                                          const VkCommandBuffer&        cmdBuffer,
@@ -272,7 +289,7 @@ class BaseTestInstance : public TestInstance
 public:
        BaseTestInstance (Context& context, const ResourceDescription& resourceDesc, const OperationSupport& writeOp, const OperationSupport& readOp, PipelineCacheData& pipelineCacheData)
                : TestInstance          (context)
-               , m_queues                      (new MultiQueues(context))
+               , m_queues                      (MultiQueues::getInstance(context))
                , m_opContext           (new OperationContext(context, pipelineCacheData, m_queues->getDeviceInterface(), m_queues->getDevice(), m_queues->getAllocator()))
                , m_resourceDesc        (resourceDesc)
                , m_writeOp                     (writeOp)
@@ -281,7 +298,7 @@ public:
        }
 
 protected:
-       const UniquePtr<MultiQueues>            m_queues;
+       const SharedPtr<MultiQueues>            m_queues;
        const UniquePtr<OperationContext>       m_opContext;
        const ResourceDescription                       m_resourceDesc;
        const OperationSupport&                         m_writeOp;
@@ -583,11 +600,19 @@ void createTests (tcu::TestCaseGroup* group, PipelineCacheData* pipelineCacheDat
        }
 }
 
+void cleanupGroup (tcu::TestCaseGroup* group, PipelineCacheData* pipelineCacheData)
+{
+       DE_UNREF(group);
+       DE_UNREF(pipelineCacheData);
+       // Destroy singleton object
+       MultiQueues::destroy();
+}
+
 } // anonymous
 
 tcu::TestCaseGroup* createSynchronizedOperationMultiQueueTests (tcu::TestContext& testCtx, PipelineCacheData& pipelineCacheData)
 {
-       return createTestGroup(testCtx, "multi_queue", "Synchronization of a memory-modifying operation", createTests, &pipelineCacheData);
+       return createTestGroup(testCtx, "multi_queue", "Synchronization of a memory-modifying operation", createTests, &pipelineCacheData, cleanupGroup);
 }
 
 } // synchronization
index d1148f9..89e1766 100644 (file)
 #include "vkDeviceUtil.hpp"
 #include "vkPlatform.hpp"
 #include "vkCmdUtil.hpp"
-
 #include "vktTestCaseUtil.hpp"
+#include "deSharedPtr.hpp"
 
 #include "vktSynchronizationUtil.hpp"
 #include "vktSynchronizationOperation.hpp"
 #include "vktSynchronizationOperationTestData.hpp"
 #include "vktExternalMemoryUtil.hpp"
+#include "vktTestGroupUtil.hpp"
 
 #include "tcuResultCollector.hpp"
 #include "tcuTestLog.hpp"
@@ -71,6 +72,8 @@ namespace synchronization
 {
 namespace
 {
+using namespace vk;
+using de::SharedPtr;
 
 static const ResourceDescription s_resourcesWin32KeyedMutex[] =
 {
@@ -1238,11 +1241,9 @@ class DX11OperationSupport
 {
 public:
        DX11OperationSupport (const vk::InstanceInterface&      vki,
-                                                 vk::VkPhysicalDevice                  physicalDevice,
-                                                 const ResourceDescription&    resourceDesc)
-               : m_resourceDesc                        (resourceDesc)
+                                                 vk::VkPhysicalDevice                  physicalDevice)
 #if (DE_OS == DE_OS_WIN32)
-               , m_hD3D11Lib                                   (0)
+               : m_hD3D11Lib                                   (0)
                , m_hD3DX11Lib                                  (0)
                , m_hD3DCompilerLib                             (0)
                , m_hDxgiLib                                    (0)
@@ -1406,7 +1407,6 @@ public:
        }
 
 private:
-       const ResourceDescription       m_resourceDesc;
 
 #if (DE_OS == DE_OS_WIN32)
        typedef HRESULT                         (WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter*,
@@ -1432,6 +1432,55 @@ private:
 #endif
 };
 
+// Class to wrap a singleton instance and device
+class InstanceAndDevice
+{
+       InstanceAndDevice       (const Context& context)
+               : m_instance            (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
+               , m_vki                         (context.getPlatformInterface(), *m_instance)
+               , m_physicalDevice      (getPhysicalDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
+               , m_logicalDevice       (createDevice(context.getUsedApiVersion(), context.getPlatformInterface(), *m_instance, m_vki, m_physicalDevice))
+               , m_supportDX11         (new DX11OperationSupport(m_vki, m_physicalDevice))
+       {
+       }
+
+public:
+
+       static const vk::Unique<vk::VkInstance>& getInstance(const Context& context)
+       {
+               if (!m_instanceAndDevice)
+                       m_instanceAndDevice = SharedPtr<InstanceAndDevice>(new InstanceAndDevice(context));
+
+               return m_instanceAndDevice->m_instance;
+       }
+       static const Unique<vk::VkDevice>& getDevice()
+       {
+               DE_ASSERT(m_instanceAndDevice);
+               return m_instanceAndDevice->m_logicalDevice;
+       }
+       static const de::UniquePtr<DX11OperationSupport>& getSupportDX11()
+       {
+               DE_ASSERT(m_instanceAndDevice);
+               return m_instanceAndDevice->m_supportDX11;
+       }
+
+       static void destroy()
+       {
+               m_instanceAndDevice.clear();
+       }
+
+private:
+       const Unique<vk::VkInstance>                            m_instance;
+       const vk::InstanceDriver                                        m_vki;
+       const vk::VkPhysicalDevice                                      m_physicalDevice;
+       const Unique<vk::VkDevice>                                      m_logicalDevice;
+       const de::UniquePtr<DX11OperationSupport>       m_supportDX11;
+
+       static SharedPtr<InstanceAndDevice>     m_instanceAndDevice;
+};
+SharedPtr<InstanceAndDevice>           InstanceAndDevice::m_instanceAndDevice;
+
+
 class Win32KeyedMutexTestInstance : public TestInstance
 {
 public:
@@ -1445,17 +1494,15 @@ private:
        const de::UniquePtr<OperationSupport>                           m_supportWriteOp;
        const de::UniquePtr<OperationSupport>                           m_supportReadOp;
 
-       const vk::Unique<vk::VkInstance>                                        m_instance;
+       const vk::Unique<vk::VkInstance>&                                       m_instance;
 
        const vk::InstanceDriver                                                        m_vki;
        const vk::VkPhysicalDevice                                                      m_physicalDevice;
        const std::vector<vk::VkQueueFamilyProperties>          m_queueFamilies;
        const std::vector<deUint32>                                                     m_queueFamilyIndices;
-       const vk::Unique<vk::VkDevice>                                          m_device;
+       const vk::Unique<vk::VkDevice>&                                         m_device;
        const vk::DeviceDriver                                                          m_vkd;
 
-       const de::UniquePtr<DX11OperationSupport>                       m_supportDX11;
-
        const vk::VkExternalMemoryHandleTypeFlagBits            m_memoryHandleType;
 
        // \todo Should this be moved to the group same way as in the other tests?
@@ -1473,17 +1520,15 @@ Win32KeyedMutexTestInstance::Win32KeyedMutexTestInstance        (Context&               context,
        , m_supportWriteOp                      (makeOperationSupport(config.writeOp, config.resource))
        , m_supportReadOp                       (makeOperationSupport(config.readOp, config.resource))
 
-       , m_instance                            (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
+       , m_instance                            (InstanceAndDevice::getInstance(context))
 
        , m_vki                                         (context.getPlatformInterface(), *m_instance)
        , m_physicalDevice                      (getPhysicalDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
        , m_queueFamilies                       (vk::getPhysicalDeviceQueueFamilyProperties(m_vki, m_physicalDevice))
        , m_queueFamilyIndices          (getFamilyIndices(m_queueFamilies))
-       , m_device                                      (createDevice(context.getUsedApiVersion(), context.getPlatformInterface(), *m_instance, m_vki, m_physicalDevice))
+       , m_device                                      (InstanceAndDevice::getDevice())
        , m_vkd                                         (context.getPlatformInterface(), *m_instance, *m_device)
 
-       , m_supportDX11                         (new DX11OperationSupport(m_vki, m_physicalDevice, config.resource))
-
        , m_memoryHandleType            ((m_config.resource.type == RESOURCE_TYPE_IMAGE) ? m_config.memoryHandleTypeImage : m_config.memoryHandleTypeBuffer)
 
        , m_resultCollector                     (context.getTestContext().getLog())
@@ -1605,7 +1650,7 @@ tcu::TestStatus Win32KeyedMutexTestInstance::iterate (void)
                if (!checkQueueFlags(m_queueFamilies[m_queueNdx].queueFlags, vk::VK_QUEUE_GRAPHICS_BIT))
                        TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
 
-               const de::UniquePtr<DX11Operation>              dx11Op                          (m_supportDX11->build(m_config.resource, m_memoryHandleType));
+               const de::UniquePtr<DX11Operation>              dx11Op                          (InstanceAndDevice::getSupportDX11()->build(m_config.resource, m_memoryHandleType));
 
                NativeHandle nativeHandleWrite = dx11Op->getNativeHandle(DX11Operation::BUFFER_VK_WRITE);
                const de::UniquePtr<Resource>                   resourceWrite           (importResource(m_vkd, *m_device, m_config.resource, m_queueFamilyIndices, *m_supportReadOp, *m_supportWriteOp, nativeHandleWrite, m_memoryHandleType));
@@ -1800,8 +1845,9 @@ struct Progs
 
 } // anonymous
 
-tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
+static void createTests (tcu::TestCaseGroup* group)
 {
+       tcu::TestContext& testCtx = group->getTestContext();
        const struct
        {
                vk::VkExternalMemoryHandleTypeFlagBits                  memoryHandleTypeBuffer;
@@ -1820,7 +1866,6 @@ tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
                        "_kmt"
                },
        };
-       de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "win32_keyed_mutex", ""));
 
        for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
        for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
@@ -1859,8 +1904,18 @@ tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
                if (!empty)
                        group->addChild(opGroup.release());
        }
+}
+
+static void cleanupGroup (tcu::TestCaseGroup* group)
+{
+       DE_UNREF(group);
+       // Destroy singleton object
+       InstanceAndDevice::destroy();
+}
 
-       return group.release();
+tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
+{
+       return createTestGroup(testCtx, "win32_keyed_mutex", "", createTests, cleanupGroup);
 }
 
 } // synchronization
index 466dd19..057c300 100644 (file)
@@ -29,9 +29,11 @@ namespace vkt
 TestGroupHelper0::TestGroupHelper0 (tcu::TestContext&  testCtx,
                                                                        const std::string&      name,
                                                                        const std::string&      description,
-                                                                       CreateChildrenFunc      createChildren)
+                                                                       CreateChildrenFunc      createChildren,
+                                                                       CleanupGroupFunc        cleanupGroup)
        : tcu::TestCaseGroup    (testCtx, name.c_str(), description.c_str())
        , m_createChildren              (createChildren)
+       , m_cleanupGroup                (cleanupGroup)
 {
 }
 
@@ -44,4 +46,10 @@ void TestGroupHelper0::init (void)
        m_createChildren(this);
 }
 
+void TestGroupHelper0::deinit(void)
+{
+       if (m_cleanupGroup)
+               m_cleanupGroup(this);
+}
+
 } // vkt
index a6e504c..115f3d1 100644 (file)
@@ -33,17 +33,21 @@ class TestGroupHelper0 : public tcu::TestCaseGroup
 {
 public:
        typedef void (*CreateChildrenFunc) (tcu::TestCaseGroup* testGroup);
+       typedef void (*CleanupGroupFunc) (tcu::TestCaseGroup* testGroup);
 
                                                                TestGroupHelper0        (tcu::TestContext&              testCtx,
                                                                                                         const std::string&             name,
                                                                                                         const std::string&             description,
-                                                                                                        CreateChildrenFunc             createChildren);
+                                                                                                        CreateChildrenFunc             createChildren,
+                                                                                                        CleanupGroupFunc               cleanupGroup);
                                                                ~TestGroupHelper0       (void);
 
        void                                            init                            (void);
+       void                                            deinit                          (void);
 
 private:
        const CreateChildrenFunc        m_createChildren;
+       const CleanupGroupFunc          m_cleanupGroup;
 };
 
 template<typename Arg0>
@@ -51,30 +55,36 @@ class TestGroupHelper1 : public tcu::TestCaseGroup
 {
 public:
        typedef void (*CreateChildrenFunc) (tcu::TestCaseGroup* testGroup, Arg0 arg0);
+       typedef void (*CleanupGroupFunc) (tcu::TestCaseGroup* testGroup, Arg0 arg0);
 
                                                                TestGroupHelper1        (tcu::TestContext&              testCtx,
                                                                                                         const std::string&             name,
                                                                                                         const std::string&             description,
                                                                                                         CreateChildrenFunc             createChildren,
-                                                                                                        const Arg0&                    arg0)
+                                                                                                        const Arg0&                    arg0,
+                                                                                                        CleanupGroupFunc               cleanupGroup)
                                                                        : tcu::TestCaseGroup    (testCtx, name.c_str(), description.c_str())
                                                                        , m_createChildren              (createChildren)
+                                                                       , m_cleanupGroup                (cleanupGroup)
                                                                        , m_arg0                                (arg0)
                                                                {}
 
        void                                            init                            (void) { m_createChildren(this, m_arg0); }
+       void                                            deinit                          (void) { if (m_cleanupGroup) m_cleanupGroup(this, m_arg0); }
 
 private:
        const CreateChildrenFunc        m_createChildren;
+       const CleanupGroupFunc          m_cleanupGroup;
        const Arg0                                      m_arg0;
 };
 
-inline tcu::TestCaseGroup* createTestGroup (tcu::TestContext&                                          testCtx,
-                                                                                       const std::string&                                              name,
-                                                                                       const std::string&                                              description,
-                                                                                       TestGroupHelper0::CreateChildrenFunc    createChildren)
+inline tcu::TestCaseGroup* createTestGroup (tcu::TestContext&                                                                          testCtx,
+                                                                                       const std::string&                                                                              name,
+                                                                                       const std::string&                                                                              description,
+                                                                                       TestGroupHelper0::CreateChildrenFunc                                    createChildren,
+                                                                                       TestGroupHelper0::CleanupGroupFunc                                              cleanupGroup = DE_NULL)
 {
-       return new TestGroupHelper0(testCtx, name, description, createChildren);
+       return new TestGroupHelper0(testCtx, name, description, createChildren, cleanupGroup);
 }
 
 template<typename Arg0>
@@ -82,9 +92,10 @@ tcu::TestCaseGroup* createTestGroup (tcu::TestContext&                                                                               testCtx,
                                                                         const std::string&                                                                             name,
                                                                         const std::string&                                                                             description,
                                                                         typename TestGroupHelper1<Arg0>::CreateChildrenFunc    createChildren,
-                                                                        Arg0                                                                                                   arg0)
+                                                                        Arg0                                                                                                   arg0,
+                                                                        typename TestGroupHelper1<Arg0>::CleanupGroupFunc              cleanupGroup = DE_NULL)
 {
-       return new TestGroupHelper1<Arg0>(testCtx, name, description, createChildren, arg0);
+       return new TestGroupHelper1<Arg0>(testCtx, name, description, createChildren, arg0, cleanupGroup);
 }
 
 inline void addTestGroup (tcu::TestCaseGroup*                                  parent,
@@ -100,9 +111,10 @@ void addTestGroup (tcu::TestCaseGroup*                                                                     parent,
                                   const std::string&                                                                   name,
                                   const std::string&                                                                   description,
                                   typename TestGroupHelper1<Arg0>::CreateChildrenFunc  createChildren,
-                                  Arg0                                                                                                 arg0)
+                                  Arg0                                                                                                 arg0,
+                                  typename TestGroupHelper1<Arg0>::CleanupGroupFunc    cleanupGroup = DE_NULL)
 {
-       parent->addChild(createTestGroup<Arg0>(parent->getTestContext(), name, description, createChildren, arg0));
+       parent->addChild(createTestGroup<Arg0>(parent->getTestContext(), name, description, createChildren, arg0, cleanupGroup));
 }
 
 } // vkt