Capture early errors on instance creation
authorRicardo Garcia <rgarcia@igalia.com>
Wed, 2 Jun 2021 11:34:48 +0000 (13:34 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 10 Jun 2021 09:15:08 +0000 (09:15 +0000)
This commit makes CTS pass a VkDebugReportCallbackCreateInfoEXT
structure in the pNext chain of VkInstanceCreateInfo when creating the
default and other custom instances if validation is enabled from the
command line.

To achieve this, the DebugReportRecorder class has been uncoupled from
the instance and it's no longer responsible of owning the debug report
callback object (VkDebugReportCallbackEXT) that can be created using an
instance. That responsibility now falls into the default device or
custom instance wrapping objects.

This makes it possible to use the DebugReportRecorder in a
VkDebugReportCallbackCreateInfoEXT structure chained when creating
instances before they actually exist, and errors reported during the
instance creation process are handled by the recorder together with
other errors like validation errors.

In addition, the enumerate_devices_alloc_leak test has been modified to
use a custom instance (so it has validation enabled if requested) and
the API tooling info tests have been changed to use the custom instance
creation wrapper function createCustomInstanceFromContext().

Custom instance creation has been improved to detect the lack of
installed validation layers in order to avoid crashes.

Due to these changes affecting the default device and how validation is
enabled when requested, all tests are marked as affected.

Affected tests:
dEQP-VK.*

Components: Vulkan
VK-GL-CTS issue: 2952

Change-Id: I27b78e3cb101142416477ee2460283f917f58a4e

external/vulkancts/framework/vulkan/vkDebugReportUtil.cpp
external/vulkancts/framework/vulkan/vkDebugReportUtil.hpp
external/vulkancts/framework/vulkan/vkDeviceUtil.cpp
external/vulkancts/framework/vulkan/vkDeviceUtil.hpp
external/vulkancts/modules/vulkan/api/vktApiDeviceInitializationTests.cpp
external/vulkancts/modules/vulkan/api/vktApiToolingInfoTests.cpp
external/vulkancts/modules/vulkan/vktCustomInstancesDevices.cpp
external/vulkancts/modules/vulkan/vktCustomInstancesDevices.hpp
external/vulkancts/modules/vulkan/vktTestCase.cpp

index fbc78e2..ba739f3 100644 (file)
@@ -134,9 +134,19 @@ VKAPI_ATTR VkBool32        VKAPI_CALL debugReportCallback (VkDebugReportFlagsEXT           flags
        return VK_FALSE;
 }
 
-Move<VkDebugReportCallbackEXT> createCallback (const InstanceInterface&                                vki,
-                                                                                          VkInstance                                                   instance,
-                                                                                          DebugReportRecorder*                                 recorder)
+} // anonymous
+
+DebugReportRecorder::DebugReportRecorder (bool printValidationErrors)
+       : m_messages            (1024)
+       , m_print_errors        (printValidationErrors)
+{
+}
+
+DebugReportRecorder::~DebugReportRecorder (void)
+{
+}
+
+VkDebugReportCallbackCreateInfoEXT DebugReportRecorder::makeCreateInfo (void)
 {
        const VkDebugReportFlagsEXT                                     allFlags        = VK_DEBUG_REPORT_INFORMATION_BIT_EXT
                                                                                                                        | VK_DEBUG_REPORT_WARNING_BIT_EXT
@@ -147,26 +157,19 @@ Move<VkDebugReportCallbackEXT> createCallback (const InstanceInterface&                           vki,
        const VkDebugReportCallbackCreateInfoEXT        createInfo      =
        {
                VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
-               DE_NULL,
+               nullptr,
                allFlags,
                debugReportCallback,
-               recorder,
+               this,
        };
 
-       return createDebugReportCallbackEXT(vki, instance, &createInfo);
-}
-
-} // anonymous
-
-DebugReportRecorder::DebugReportRecorder (const InstanceInterface& vki, VkInstance instance, bool printValidationErrors)
-       : m_messages            (1024)
-       , m_callback            (createCallback(vki, instance, this))
-       , m_print_errors        (printValidationErrors)
-{
+       return createInfo;
 }
 
-DebugReportRecorder::~DebugReportRecorder (void)
+Move<VkDebugReportCallbackEXT> DebugReportRecorder::createCallback (const InstanceInterface& vki, VkInstance instance)
 {
+       const auto createInfo = makeCreateInfo();
+       return createDebugReportCallbackEXT(vki, instance, &createInfo);
 }
 
 bool isDebugReportSupported (const PlatformInterface& vkp)
index 52c3315..e7a82d6 100644 (file)
@@ -81,27 +81,29 @@ struct DebugReportMessage
        }
 };
 
-std::ostream&  operator<<      (std::ostream& str, const DebugReportMessage& message);
+std::ostream& operator<< (std::ostream& str, const DebugReportMessage& message);
 
 class DebugReportRecorder
 {
 public:
        using MessageList = de::AppendList<DebugReportMessage>;
 
-                                                                                       DebugReportRecorder             (const InstanceInterface& vki, VkInstance instance, bool printValidationErrors);
+                                                                                       DebugReportRecorder             (bool printValidationErrors);
                                                                                        ~DebugReportRecorder    (void);
 
        MessageList&                                                    getMessages                             (void) { return m_messages; }
        void                                                                    clearMessages                   (void) { m_messages.clear(); }
        bool                                                                    errorPrinting                   (void) const { return m_print_errors; }
 
+       VkDebugReportCallbackCreateInfoEXT              makeCreateInfo                  (void);
+       Move<VkDebugReportCallbackEXT>                  createCallback                  (const InstanceInterface& vki, VkInstance instance);
+
 private:
        MessageList                                                             m_messages;
-       const Unique<VkDebugReportCallbackEXT>  m_callback;
        const bool                                                              m_print_errors;
 };
 
-bool   isDebugReportSupported          (const PlatformInterface& vkp);
+bool isDebugReportSupported (const PlatformInterface& vkp);
 
 } // vk
 
index 0ffdf7e..3b397ba 100644 (file)
@@ -42,6 +42,7 @@ Move<VkInstance> createDefaultInstance (const PlatformInterface&              vkPlatform,
                                                                                deUint32                                                apiVersion,
                                                                                const vector<string>&                   enabledLayers,
                                                                                const vector<string>&                   enabledExtensions,
+                                                                               DebugReportRecorder*                    recorder,
                                                                                const VkAllocationCallbacks*    pAllocator)
 {
        bool                    validationEnabled       = (!enabledLayers.empty());
@@ -55,6 +56,8 @@ Move<VkInstance> createDefaultInstance (const PlatformInterface&              vkPlatform,
 
                if (!de::contains(begin(actualExtensions), end(actualExtensions), "VK_EXT_debug_report"))
                        actualExtensions.push_back("VK_EXT_debug_report");
+
+               DE_ASSERT(recorder);
        }
 
        vector<const char*>             layerNamePtrs           (enabledLayers.size());
@@ -76,16 +79,19 @@ Move<VkInstance> createDefaultInstance (const PlatformInterface&            vkPlatform,
                qpGetReleaseId(),                                               // engineVersion
                apiVersion                                                              // apiVersion
        };
+
+       const VkDebugReportCallbackCreateInfoEXT callbackInfo = (validationEnabled ? recorder->makeCreateInfo() : initVulkanStructure());
+
        const struct VkInstanceCreateInfo       instanceInfo    =
        {
                VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
-               DE_NULL,
+               (validationEnabled ? &callbackInfo : nullptr),
                (VkInstanceCreateFlags)0,
                &appInfo,
                (deUint32)layerNamePtrs.size(),
-               (validationEnabled ? layerNamePtrs.data() : DE_NULL),
+               (validationEnabled ? layerNamePtrs.data() : nullptr),
                (deUint32)extensionNamePtrs.size(),
-               (extensionNamePtrs.empty() ? DE_NULL : extensionNamePtrs.data()),
+               (extensionNamePtrs.empty() ? nullptr : extensionNamePtrs.data()),
        };
 
        return createInstance(vkPlatform, &instanceInfo, pAllocator);
@@ -93,7 +99,7 @@ Move<VkInstance> createDefaultInstance (const PlatformInterface&              vkPlatform,
 
 Move<VkInstance> createDefaultInstance (const PlatformInterface& vkPlatform, deUint32 apiVersion)
 {
-       return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), DE_NULL);
+       return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), nullptr, nullptr);
 }
 
 deUint32 chooseDeviceIndex (const InstanceInterface& vkInstance, const VkInstance instance, const tcu::CommandLine& cmdLine)
index cebdf15..740eeb5 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "vkDefs.hpp"
 #include "vkRef.hpp"
+#include "vkDebugReportUtil.hpp"
 
 #include <vector>
 #include <string>
@@ -44,7 +45,8 @@ Move<VkInstance>      createDefaultInstance   (const PlatformInterface&                       vkPlatform,
                                                                                         deUint32                                                       apiVersion,
                                                                                         const std::vector<std::string>&        enabledLayers,
                                                                                         const std::vector<std::string>&        enabledExtensions,
-                                                                                        const VkAllocationCallbacks*           pAllocator      = DE_NULL);
+                                                                                        DebugReportRecorder*                           recorder = nullptr,
+                                                                                        const VkAllocationCallbacks*           pAllocator = nullptr);
 
 deUint32                       chooseDeviceIndex               (const InstanceInterface&                       vkInstance,
                                                                                         const VkInstance                                       instance,
index 9f2283c..6e1c383 100644 (file)
@@ -563,18 +563,16 @@ tcu::TestStatus enumerateDevicesAllocLeakTest(Context& context)
 
        typedef AllocationCallbackRecorder::RecordIterator RecordIterator;
 
-       const PlatformInterface&        vkp                             (context.getPlatformInterface());
-       const deUint32                          apiVersion              (context.getUsedApiVersion());
        DeterministicFailAllocator      objAllocator    (getSystemAllocator(), DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0);
        AllocationCallbackRecorder      recorder                (objAllocator.getCallbacks(), 128);
-       Move<VkInstance>                        instance                (vk::createDefaultInstance(vkp, apiVersion, {}, {}, recorder.getCallbacks()));
-       InstanceDriver                          vki                             (vkp, *instance);
-       vector<VkPhysicalDevice>        devices                 (enumeratePhysicalDevices(vki, *instance));
+       const auto                                      instance                = createCustomInstanceFromContext(context, recorder.getCallbacks(), true);
+       const auto&                                     vki                             = instance.getDriver();
+       vector<VkPhysicalDevice>        devices                 (enumeratePhysicalDevices(vki, instance));
        RecordIterator                          recordToCheck   (recorder.getRecordsEnd());
 
        try
        {
-               devices = enumeratePhysicalDevices(vki, *instance);
+               devices = enumeratePhysicalDevices(vki, instance);
        }
        catch (const vk::OutOfMemoryError& e)
        {
index 96d906d..ddd0939 100644 (file)
@@ -66,21 +66,7 @@ void checkSupport (Context& context)
 
 CustomInstance createCustomInstance (Context& context, bool allowLayers)
 {
-       std::vector<const char*>                enabledLayers;
-       std::vector<std::string>                enabledLayersStr;
-       const std::vector<std::string>  enabledExtensions;
-
-       const deUint32                                  apiVersion      = context.getUsedApiVersion();
-       const vk::PlatformInterface&    vkp                     = context.getPlatformInterface();
-
-       if (allowLayers)
-       {
-               enabledLayers           = getValidationLayers(context.getPlatformInterface());
-               enabledLayersStr        = std::vector<std::string>(begin(enabledLayers), end(enabledLayers));
-       }
-
-       Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, enabledExtensions, DE_NULL);
-       return CustomInstance(context, instance, !enabledLayers.empty(), context.getTestContext().getCommandLine().printValidationErrors());
+       return createCustomInstanceFromContext(context, nullptr, allowLayers);
 }
 
 bool checkToolsProperties (Context& context, const std::vector<VkPhysicalDeviceToolPropertiesEXT>& deviceToolPropertiesEXTArray)
index be3c330..0cbb88c 100644 (file)
 #include "vkRefUtil.hpp"
 #include "vkQueryUtil.hpp"
 #include "vkDeviceUtil.hpp"
+#include "vkDebugReportUtil.hpp"
 #include "tcuCommandLine.hpp"
 #include "vktCustomInstancesDevices.hpp"
 
 #include <algorithm>
+#include <memory>
+#include <set>
 
 using std::vector;
 using std::string;
@@ -36,6 +39,8 @@ using vk::Move;
 using vk::VkInstance;
 using vk::InstanceDriver;
 using vk::DebugReportRecorder;
+using vk::VkDebugReportCallbackCreateInfoEXT;
+using vk::VkDebugReportCallbackEXT;
 
 namespace vkt
 {
@@ -88,19 +93,21 @@ vector<const char*> getValidationLayers (const vk::InstanceInterface& vki, vk::V
        return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
 }
 
-CustomInstance::CustomInstance (Context& context, Move<VkInstance> instance, bool enableDebugReportRecorder, bool printValidationErrors)
+CustomInstance::CustomInstance (Context& context, Move<VkInstance> instance, std::unique_ptr<vk::DebugReportRecorder>& recorder)
        : m_context             (&context)
+       , m_recorder    (recorder.release())
        , m_instance    (instance)
        , m_driver              (new InstanceDriver(context.getPlatformInterface(), *m_instance))
-       , m_recorder    (enableDebugReportRecorder ? (new DebugReportRecorder(*m_driver, *m_instance, printValidationErrors)) : nullptr)
+       , m_callback    (m_recorder ? m_recorder->createCallback(*m_driver, *m_instance) : Move<VkDebugReportCallbackEXT>())
 {
 }
 
 CustomInstance::CustomInstance ()
        : m_context             (nullptr)
+       , m_recorder    (nullptr)
        , m_instance    ()
        , m_driver              (nullptr)
-       , m_recorder    (nullptr)
+       , m_callback    ()
 {
 }
 
@@ -126,9 +133,10 @@ CustomInstance&    CustomInstance::operator= (CustomInstance&& other)
 void CustomInstance::swap (CustomInstance& other)
 {
        std::swap(m_context, other.m_context);
+       m_recorder.swap(other.m_recorder);
        Move<VkInstance> aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
        m_driver.swap(other.m_driver);
-       m_recorder.swap(other.m_recorder);
+       Move<VkDebugReportCallbackEXT> aux2 = m_callback; m_callback = other.m_callback; other.m_callback = aux2;
 }
 
 CustomInstance::operator VkInstance () const
@@ -149,19 +157,21 @@ void CustomInstance::collectMessages ()
 
 UncheckedInstance::UncheckedInstance ()
        : m_context             (nullptr)
+       , m_recorder    (nullptr)
        , m_allocator   (nullptr)
        , m_instance    (DE_NULL)
        , m_driver              (nullptr)
-       , m_recorder    (nullptr)
+       , m_callback    ()
 {
 }
 
-UncheckedInstance::UncheckedInstance (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, bool enableDebugReportRecorder, bool printValidationErrors)
+UncheckedInstance::UncheckedInstance (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, std::unique_ptr<DebugReportRecorder>& recorder)
        : m_context             (&context)
+       , m_recorder    (recorder.release())
        , m_allocator   (pAllocator)
        , m_instance    (instance)
        , m_driver              ((m_instance != DE_NULL) ? new InstanceDriver(context.getPlatformInterface(), m_instance) : nullptr)
-       , m_recorder    ((enableDebugReportRecorder && m_instance != DE_NULL) ? (new DebugReportRecorder(*m_driver, m_instance, printValidationErrors)) : nullptr)
+       , m_callback    (m_recorder ? m_recorder->createCallback(*m_driver, m_instance) : Move<VkDebugReportCallbackEXT>())
 {
 }
 
@@ -180,10 +190,11 @@ UncheckedInstance::~UncheckedInstance ()
 void UncheckedInstance::swap (UncheckedInstance& other)
 {
        std::swap(m_context, other.m_context);
+       m_recorder.swap(other.m_recorder);
        std::swap(m_allocator, other.m_allocator);
        vk::VkInstance aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
        m_driver.swap(other.m_driver);
-       m_recorder.swap(other.m_recorder);
+       Move<VkDebugReportCallbackEXT> aux2 = m_callback; m_callback = other.m_callback; other.m_callback = aux2;
 }
 
 UncheckedInstance::UncheckedInstance (UncheckedInstance&& other)
@@ -214,36 +225,54 @@ CustomInstance createCustomInstanceWithExtensions (Context& context, const std::
        vector<const char*>     enabledLayers;
        vector<string>          enabledLayersStr;
        const auto&                     cmdLine                                 = context.getTestContext().getCommandLine();
-       const bool                      validationEnabled               = (cmdLine.isValidationEnabled() && allowLayers);
+       const bool                      validationRequested             = (cmdLine.isValidationEnabled() && allowLayers);
        const bool                      printValidationErrors   = cmdLine.printValidationErrors();
 
-       if (validationEnabled)
+       if (validationRequested)
        {
                enabledLayers = getValidationLayers(context.getPlatformInterface());
                enabledLayersStr = vector<string>(begin(enabledLayers), end(enabledLayers));
        }
 
+       const bool validationEnabled = !enabledLayers.empty();
+
        // Filter extension list and throw NotSupported if a required extension is not supported.
        const deUint32                                                                  apiVersion                      = context.getUsedApiVersion();
        const vk::PlatformInterface&                                    vkp                                     = context.getPlatformInterface();
-       const std::vector<vk::VkExtensionProperties>    availableExtensions     = vk::enumerateInstanceExtensionProperties(vkp, DE_NULL);
-       vector<string>                                                                  extensionPtrs;
+       const vector<vk::VkExtensionProperties>                 availableExtensions     = vk::enumerateInstanceExtensionProperties(vkp, DE_NULL);
+       std::set<string>                                                                usedExtensions;
 
+       // Get list of available extension names.
        vector<string> availableExtensionNames;
        for (const auto& ext : availableExtensions)
                availableExtensionNames.push_back(ext.extensionName);
 
+       // Filter duplicates and remove core extensions.
        for (const auto& ext : extensions)
        {
+               if (!vk::isCoreInstanceExtension(apiVersion, ext))
+                       usedExtensions.insert(ext);
+       }
+
+       // Add debug extension if validation is enabled.
+       if (validationEnabled)
+               usedExtensions.insert("VK_EXT_debug_report");
+
+       // Check extension support.
+       for (const auto& ext : usedExtensions)
+       {
                if (!vk::isInstanceExtensionSupported(apiVersion, availableExtensionNames, ext))
                        TCU_THROW(NotSupportedError, ext + " is not supported");
-
-               if (!vk::isCoreInstanceExtension(apiVersion, ext))
-                       extensionPtrs.push_back(ext);
        }
 
-       Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, extensionPtrs, pAllocator);
-       return CustomInstance(context, instance, validationEnabled, printValidationErrors);
+       std::unique_ptr<DebugReportRecorder> debugReportRecorder;
+       if (validationEnabled)
+               debugReportRecorder.reset(new DebugReportRecorder(printValidationErrors));
+
+       // Create custom instance.
+       const vector<string> usedExtensionsVec(begin(usedExtensions), end(usedExtensions));
+       Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, debugReportRecorder.get(), pAllocator);
+       return CustomInstance(context, instance, debugReportRecorder);
 }
 
 CustomInstance createCustomInstanceWithExtension (Context& context, const std::string& extension, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
@@ -281,13 +310,15 @@ vector<const char*> addDebugReportExt(const vk::PlatformInterface& vkp, const vk
 
 CustomInstance createCustomInstanceFromInfo (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
 {
-       vector<const char*>                             enabledLayers;
-       vector<const char*>                             enabledExtensions;
-       vk::VkInstanceCreateInfo                createInfo                              = *instanceCreateInfo;
-       const auto&                                             cmdLine                                 = context.getTestContext().getCommandLine();
-       const bool                                              validationEnabled               = cmdLine.isValidationEnabled();
-       const bool                                              printValidationErrors   = cmdLine.printValidationErrors();
-       const vk::PlatformInterface&    vkp                                             = context.getPlatformInterface();
+       vector<const char*>                                             enabledLayers;
+       vector<const char*>                                             enabledExtensions;
+       vk::VkInstanceCreateInfo                                createInfo                              = *instanceCreateInfo;
+       const auto&                                                             cmdLine                                 = context.getTestContext().getCommandLine();
+       const bool                                                              validationEnabled               = cmdLine.isValidationEnabled();
+       const bool                                                              printValidationErrors   = cmdLine.printValidationErrors();
+       const vk::PlatformInterface&                    vkp                                             = context.getPlatformInterface();
+       std::unique_ptr<DebugReportRecorder>    recorder;
+       VkDebugReportCallbackCreateInfoEXT              callbackInfo;
 
        if (validationEnabled && allowLayers)
        {
@@ -303,21 +334,28 @@ CustomInstance createCustomInstanceFromInfo (Context& context, const vk::VkInsta
                enabledExtensions = addDebugReportExt(vkp, createInfo);
                createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
                createInfo.ppEnabledExtensionNames = enabledExtensions.data();
+
+               recorder.reset(new DebugReportRecorder(printValidationErrors));
+               callbackInfo            = recorder->makeCreateInfo();
+               callbackInfo.pNext      = createInfo.pNext;
+               createInfo.pNext        = &callbackInfo;
        }
 
-       return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), validationEnabled, printValidationErrors);
+       return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), recorder);
 }
 
 vk::VkResult createUncheckedInstance (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, UncheckedInstance* instance, bool allowLayers)
 {
-       vector<const char*>                             enabledLayers;
-       vector<const char*>                             enabledExtensions;
-       vk::VkInstanceCreateInfo                createInfo                              = *instanceCreateInfo;
-       const auto&                                             cmdLine                                 = context.getTestContext().getCommandLine();
-       const bool                                              validationEnabled               = cmdLine.isValidationEnabled();
-       const bool                                              printValidationErrors   = cmdLine.printValidationErrors();
-       const vk::PlatformInterface&    vkp                                             = context.getPlatformInterface();
-       const bool                                              addLayers                               = (validationEnabled && allowLayers);
+       vector<const char*>                                             enabledLayers;
+       vector<const char*>                                             enabledExtensions;
+       vk::VkInstanceCreateInfo                                createInfo                              = *instanceCreateInfo;
+       const auto&                                                             cmdLine                                 = context.getTestContext().getCommandLine();
+       const bool                                                              validationEnabled               = cmdLine.isValidationEnabled();
+       const bool                                                              printValidationErrors   = cmdLine.printValidationErrors();
+       const vk::PlatformInterface&                    vkp                                             = context.getPlatformInterface();
+       const bool                                                              addLayers                               = (validationEnabled && allowLayers);
+       std::unique_ptr<DebugReportRecorder>    recorder;
+       VkDebugReportCallbackCreateInfoEXT              callbackInfo;
 
        if (addLayers)
        {
@@ -333,12 +371,18 @@ vk::VkResult createUncheckedInstance (Context& context, const vk::VkInstanceCrea
                enabledExtensions = addDebugReportExt(vkp, createInfo);
                createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
                createInfo.ppEnabledExtensionNames = enabledExtensions.data();
+
+               // Prepare debug report recorder also for instance creation.
+               recorder.reset(new DebugReportRecorder(printValidationErrors));
+               callbackInfo            = recorder->makeCreateInfo();
+               callbackInfo.pNext      = createInfo.pNext;
+               createInfo.pNext        = &callbackInfo;
        }
 
        vk::VkInstance  raw_instance = DE_NULL;
        vk::VkResult    result = vkp.createInstance(&createInfo, pAllocator, &raw_instance);
 
-       *instance = UncheckedInstance(context, raw_instance, pAllocator, addLayers, printValidationErrors);
+       *instance = UncheckedInstance(context, raw_instance, pAllocator, recorder);
 
        return result;
 }
index 12fa914..6ac2de2 100644 (file)
@@ -52,7 +52,7 @@ class CustomInstance
 {
 public:
                                                                CustomInstance                  ();
-                                                               CustomInstance                  (Context& context, vk::Move<vk::VkInstance> instance, bool enableDebugReportRecorder, bool printValidationErrors);
+                                                               CustomInstance                  (Context& context, vk::Move<vk::VkInstance> instance, std::unique_ptr<vk::DebugReportRecorder>& recorder);
                                                                CustomInstance                  (CustomInstance&& other);
                                                                ~CustomInstance                 ();
        CustomInstance&                         operator=                               (CustomInstance&& other);
@@ -65,16 +65,17 @@ public:
        CustomInstance&                         operator=                               (const CustomInstance& other) = delete;
 private:
        Context*                                                                        m_context;
+       std::unique_ptr<vk::DebugReportRecorder>        m_recorder;
        vk::Move<vk::VkInstance>                                        m_instance;
        std::unique_ptr<vk::InstanceDriver>                     m_driver;
-       std::unique_ptr<vk::DebugReportRecorder>        m_recorder;
+       vk::Move<vk::VkDebugReportCallbackEXT>          m_callback;
 };
 
 class UncheckedInstance
 {
 public:
                                                UncheckedInstance               ();
-                                               UncheckedInstance               (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, bool enableDebugReportRecorder, bool printValidationErrors);
+                                               UncheckedInstance               (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, std::unique_ptr<vk::DebugReportRecorder>& recorder);
                                                UncheckedInstance               (UncheckedInstance&& other);
                                                ~UncheckedInstance              ();
        UncheckedInstance&      operator=                               (UncheckedInstance&& other);
@@ -86,10 +87,11 @@ public:
        UncheckedInstance&      operator=                               (const UncheckedInstance& other) = delete;
 private:
        Context*                                                                        m_context;
+       std::unique_ptr<vk::DebugReportRecorder>        m_recorder;
        const vk::VkAllocationCallbacks*                        m_allocator;
        vk::VkInstance                                                          m_instance;
        std::unique_ptr<vk::InstanceDriver>                     m_driver;
-       std::unique_ptr<vk::DebugReportRecorder>        m_recorder;
+       vk::Move<vk::VkDebugReportCallbackEXT>          m_callback;
 };
 
 // Custom instances.
index 26e8be0..18df21f 100644 (file)
@@ -183,16 +183,16 @@ std::pair<deUint32, deUint32> determineDeviceVersions(const PlatformInterface& v
 }
 
 
-Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine)
+Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, DebugReportRecorder* recorder)
 {
-       const bool                                                              isValidationEnabled     = cmdLine.isValidationEnabled();
-       vector<const char*>                                             enabledLayers;
+       const bool                      isValidationEnabled     = (recorder != nullptr);
+       vector<const char*>     enabledLayers;
 
        // \note Extensions in core are not explicitly enabled even though
        //               they are in the extension list advertised to tests.
-       vector<const char*>                                             coreExtensions;
+       vector<const char*> coreExtensions;
        getCoreInstanceExtensions(apiVersion, coreExtensions);
-       vector<string>                                                  nonCoreExtensions       (removeExtensions(enabledExtensions, coreExtensions));
+       const auto nonCoreExtensions = removeExtensions(enabledExtensions, coreExtensions);
 
        if (isValidationEnabled)
        {
@@ -204,7 +204,7 @@ Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersi
                        TCU_THROW(NotSupportedError, "No validation layers found");
        }
 
-       return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions);
+       return createDefaultInstance(vkp, apiVersion, vector<string>(begin(enabledLayers), end(enabledLayers)), nonCoreExtensions, recorder);
 }
 
 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
@@ -338,6 +338,7 @@ public:
 
 private:
        using DebugReportRecorderPtr            = de::UniquePtr<vk::DebugReportRecorder>;
+       using DebugReportCallbackPtr            = vk::Move<VkDebugReportCallbackEXT>;
 
        const deUint32                                          m_maximumFrameworkVulkanVersion;
        const deUint32                                          m_availableInstanceVersion;
@@ -346,10 +347,11 @@ private:
        const std::pair<deUint32, deUint32> m_deviceVersions;
        const deUint32                                          m_usedApiVersion;
 
+       const DebugReportRecorderPtr            m_debugReportRecorder;
        const vector<string>                            m_instanceExtensions;
        const Unique<VkInstance>                        m_instance;
        const InstanceDriver                            m_instanceInterface;
-       const DebugReportRecorderPtr            m_debugReportRecorder;
+       const DebugReportCallbackPtr            m_debugReportCallback;
 
        const VkPhysicalDevice                          m_physicalDevice;
        const deUint32                                          m_deviceVersion;
@@ -373,10 +375,10 @@ deUint32 sanitizeApiVersion(deUint32 v)
        return VK_MAKE_VERSION(VK_API_VERSION_MAJOR(v), VK_API_VERSION_MINOR(v), 0 );
 }
 
-de::MovePtr<vk::DebugReportRecorder> createDebugReportRecorder (const vk::PlatformInterface& vkp, const vk::InstanceInterface& vki, vk::VkInstance instance, bool printValidationErrors)
+de::MovePtr<vk::DebugReportRecorder> createDebugReportRecorder (const vk::PlatformInterface& vkp, bool printValidationErrors)
 {
        if (isDebugReportSupported(vkp))
-               return de::MovePtr<vk::DebugReportRecorder>(new vk::DebugReportRecorder(vki, instance, printValidationErrors));
+               return de::MovePtr<vk::DebugReportRecorder>(new vk::DebugReportRecorder(printValidationErrors));
        else
                TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
 }
@@ -390,16 +392,16 @@ DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::Co
        , m_deviceVersions                                      (determineDeviceVersions(vkPlatform, m_usedInstanceVersion, cmdLine))
        , m_usedApiVersion                                      (sanitizeApiVersion(deMinu32(m_usedInstanceVersion, m_deviceVersions.first)))
 
+       , m_debugReportRecorder                         (cmdLine.isValidationEnabled()
+                                                                                ? createDebugReportRecorder(vkPlatform, cmdLine.printValidationErrors())
+                                                                                : de::MovePtr<vk::DebugReportRecorder>())
        , m_instanceExtensions                          (addCoreInstanceExtensions(filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)), m_usedApiVersion))
-       , m_instance                                            (createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine))
+       , m_instance                                            (createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, m_debugReportRecorder.get()))
 
        , m_instanceInterface                           (vkPlatform, *m_instance)
-       , m_debugReportRecorder                         (cmdLine.isValidationEnabled()
-                                                                                ? createDebugReportRecorder(vkPlatform,
-                                                                                                                                        m_instanceInterface,
-                                                                                                                                        *m_instance,
-                                                                                                                                        cmdLine.printValidationErrors())
-                                                                                : de::MovePtr<vk::DebugReportRecorder>(DE_NULL))
+       , m_debugReportCallback                         (cmdLine.isValidationEnabled()
+                                                                                ? m_debugReportRecorder->createCallback(m_instanceInterface, m_instance.get())
+                                                                                : DebugReportCallbackPtr())
        , m_physicalDevice                                      (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
        , m_deviceVersion                                       (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice).apiVersion)