| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2019 The Khronos Group Inc. |
| * Copyright (c) 2019 Valve Corporation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Auxiliar functions to help create custom devices and instances. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vkRefUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkDeviceUtil.hpp" |
| #include "tcuCommandLine.hpp" |
| #include "vktCustomInstancesDevices.hpp" |
| |
| #include <algorithm> |
| |
| using std::vector; |
| using std::string; |
| using vk::Move; |
| using vk::VkInstance; |
| using vk::InstanceDriver; |
| using vk::DebugReportRecorder; |
| |
| namespace vkt |
| { |
| |
| namespace |
| { |
| |
| vector<const char*> getValidationLayers (const vector<vk::VkLayerProperties>& supportedLayers) |
| { |
| static const char* s_magicLayer = "VK_LAYER_KHRONOS_validation"; |
| static const char* s_defaultLayers[] = |
| { |
| "VK_LAYER_LUNARG_standard_validation", // Deprecated by at least Vulkan SDK 1.1.121. |
| "VK_LAYER_GOOGLE_threading", // Deprecated by at least Vulkan SDK 1.1.121. |
| "VK_LAYER_LUNARG_parameter_validation", // Deprecated by at least Vulkan SDK 1.1.121. |
| "VK_LAYER_LUNARG_device_limits", |
| "VK_LAYER_LUNARG_object_tracker", // Deprecated by at least Vulkan SDK 1.1.121. |
| "VK_LAYER_LUNARG_image", |
| "VK_LAYER_LUNARG_core_validation", // Deprecated by at least Vulkan SDK 1.1.121. |
| "VK_LAYER_LUNARG_swapchain", |
| "VK_LAYER_GOOGLE_unique_objects" // Deprecated by at least Vulkan SDK 1.1.121. |
| }; |
| |
| vector<const char*> enabledLayers; |
| |
| if (vk::isLayerSupported(supportedLayers, vk::RequiredLayer(s_magicLayer))) |
| enabledLayers.push_back(s_magicLayer); |
| else |
| { |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx) |
| { |
| if (isLayerSupported(supportedLayers, vk::RequiredLayer(s_defaultLayers[ndx]))) |
| enabledLayers.push_back(s_defaultLayers[ndx]); |
| } |
| } |
| |
| return enabledLayers; |
| } |
| |
| } // anonymous |
| |
| |
| vector<const char*> getValidationLayers (const vk::PlatformInterface& vkp) |
| { |
| return getValidationLayers(enumerateInstanceLayerProperties(vkp)); |
| } |
| |
| vector<const char*> getValidationLayers (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice) |
| { |
| return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice)); |
| } |
| |
| CustomInstance::CustomInstance (Context& context, Move<VkInstance> instance, bool enableDebugReportRecorder, bool printValidationErrors) |
| : m_context (&context) |
| , m_instance (instance) |
| , m_driver (new InstanceDriver(context.getPlatformInterface(), *m_instance)) |
| , m_recorder (enableDebugReportRecorder ? (new DebugReportRecorder(*m_driver, *m_instance, printValidationErrors)) : nullptr) |
| { |
| } |
| |
| CustomInstance::CustomInstance () |
| : m_context (nullptr) |
| , m_instance () |
| , m_driver (nullptr) |
| , m_recorder (nullptr) |
| { |
| } |
| |
| CustomInstance::CustomInstance (CustomInstance&& other) |
| : CustomInstance() |
| { |
| this->swap(other); |
| } |
| |
| CustomInstance::~CustomInstance () |
| { |
| collectMessages(); |
| } |
| |
| CustomInstance& CustomInstance::operator= (CustomInstance&& other) |
| { |
| CustomInstance destroyer; |
| destroyer.swap(other); |
| this->swap(destroyer); |
| return *this; |
| } |
| |
| void CustomInstance::swap (CustomInstance& other) |
| { |
| std::swap(m_context, other.m_context); |
| 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); |
| } |
| |
| CustomInstance::operator VkInstance () const |
| { |
| return *m_instance; |
| } |
| |
| const vk::InstanceDriver& CustomInstance::getDriver() const |
| { |
| return *m_driver; |
| } |
| |
| void CustomInstance::collectMessages () |
| { |
| if (m_recorder) |
| collectAndReportDebugMessages(*m_recorder, *m_context); |
| } |
| |
| UncheckedInstance::UncheckedInstance () |
| : m_context (nullptr) |
| , m_allocator (nullptr) |
| , m_instance (DE_NULL) |
| , m_driver (nullptr) |
| , m_recorder (nullptr) |
| { |
| } |
| |
| UncheckedInstance::UncheckedInstance (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, bool enableDebugReportRecorder, bool printValidationErrors) |
| : m_context (&context) |
| , 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) |
| { |
| } |
| |
| UncheckedInstance::~UncheckedInstance () |
| { |
| if (m_recorder) |
| collectAndReportDebugMessages(*m_recorder, *m_context); |
| |
| if (m_instance != DE_NULL) |
| { |
| m_recorder.reset(nullptr); |
| m_driver->destroyInstance(m_instance, m_allocator); |
| } |
| } |
| |
| void UncheckedInstance::swap (UncheckedInstance& other) |
| { |
| std::swap(m_context, other.m_context); |
| 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); |
| } |
| |
| UncheckedInstance::UncheckedInstance (UncheckedInstance&& other) |
| : UncheckedInstance() |
| { |
| this->swap(other); |
| } |
| |
| UncheckedInstance& UncheckedInstance::operator= (UncheckedInstance&& other) |
| { |
| UncheckedInstance destroyer; |
| destroyer.swap(other); |
| this->swap(destroyer); |
| return *this; |
| } |
| |
| UncheckedInstance::operator vk::VkInstance () const |
| { |
| return m_instance; |
| } |
| UncheckedInstance::operator bool () const |
| { |
| return (m_instance != DE_NULL); |
| } |
| |
| CustomInstance createCustomInstanceWithExtensions (Context& context, const std::vector<std::string>& extensions, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers) |
| { |
| vector<const char*> enabledLayers; |
| vector<string> enabledLayersStr; |
| const auto& cmdLine = context.getTestContext().getCommandLine(); |
| const bool validationEnabled = (cmdLine.isValidationEnabled() && allowLayers); |
| const bool printValidationErrors = cmdLine.printValidationErrors(); |
| |
| if (validationEnabled) |
| { |
| enabledLayers = getValidationLayers(context.getPlatformInterface()); |
| enabledLayersStr = vector<string>(begin(enabledLayers), end(enabledLayers)); |
| } |
| |
| // 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; |
| |
| vector<string> availableExtensionNames; |
| for (const auto& ext : availableExtensions) |
| availableExtensionNames.push_back(ext.extensionName); |
| |
| for (const auto& ext : extensions) |
| { |
| 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); |
| } |
| |
| CustomInstance createCustomInstanceWithExtension (Context& context, const std::string& extension, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers) |
| { |
| return createCustomInstanceWithExtensions(context, std::vector<std::string>(1, extension), pAllocator, allowLayers); |
| } |
| |
| CustomInstance createCustomInstanceFromContext (Context& context, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers) |
| { |
| return createCustomInstanceWithExtensions(context, std::vector<std::string>(), pAllocator, allowLayers); |
| } |
| |
| const char kDebugReportExt[] = "VK_EXT_debug_report"; |
| |
| vector<const char*> addDebugReportExt(const vk::PlatformInterface& vkp, const vk::VkInstanceCreateInfo& createInfo) |
| { |
| if (!isDebugReportSupported(vkp)) |
| TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported"); |
| |
| vector<const char*> actualExtensions; |
| if (createInfo.enabledExtensionCount != 0u) |
| { |
| for (deUint32 i = 0u; i < createInfo.enabledExtensionCount; ++i) |
| actualExtensions.push_back(createInfo.ppEnabledExtensionNames[i]); |
| } |
| |
| if (std::find_if(begin(actualExtensions), end(actualExtensions), [](const char* name) { return (strcmp(name, kDebugReportExt) == 0); }) |
| == end(actualExtensions)) |
| { |
| actualExtensions.push_back(kDebugReportExt); |
| } |
| |
| return actualExtensions; |
| } |
| |
| 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(); |
| |
| if (validationEnabled && allowLayers) |
| { |
| // Activate some layers if requested. |
| if (createInfo.enabledLayerCount == 0u) |
| { |
| enabledLayers = getValidationLayers(vkp); |
| createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size()); |
| createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data()); |
| } |
| |
| // Make sure the debug report extension is enabled when validation is enabled. |
| enabledExtensions = addDebugReportExt(vkp, createInfo); |
| createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size()); |
| createInfo.ppEnabledExtensionNames = enabledExtensions.data(); |
| } |
| |
| return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), validationEnabled, printValidationErrors); |
| } |
| |
| 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); |
| |
| if (addLayers) |
| { |
| // Activate some layers if requested. |
| if (createInfo.enabledLayerCount == 0u) |
| { |
| enabledLayers = getValidationLayers(vkp); |
| createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size()); |
| createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data()); |
| } |
| |
| // Make sure the debug report extension is enabled when validation is enabled. |
| enabledExtensions = addDebugReportExt(vkp, createInfo); |
| createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size()); |
| createInfo.ppEnabledExtensionNames = enabledExtensions.data(); |
| } |
| |
| vk::VkInstance raw_instance = DE_NULL; |
| vk::VkResult result = vkp.createInstance(&createInfo, pAllocator, &raw_instance); |
| |
| *instance = UncheckedInstance(context, raw_instance, pAllocator, addLayers, printValidationErrors); |
| |
| return result; |
| } |
| |
| vk::Move<vk::VkDevice> createCustomDevice (bool validationEnabled, const vk::PlatformInterface& vkp, vk::VkInstance instance, const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo* pCreateInfo, const vk::VkAllocationCallbacks* pAllocator) |
| { |
| vector<const char*> enabledLayers; |
| vk::VkDeviceCreateInfo createInfo = *pCreateInfo; |
| |
| if (createInfo.enabledLayerCount == 0u && validationEnabled) |
| { |
| enabledLayers = getValidationLayers(vki, physicalDevice); |
| createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size()); |
| createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data()); |
| } |
| |
| return createDevice(vkp, instance, vki, physicalDevice, &createInfo, pAllocator); |
| } |
| |
| vk::VkResult createUncheckedDevice (bool validationEnabled, const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo* pCreateInfo, const vk::VkAllocationCallbacks* pAllocator, vk::VkDevice* pDevice) |
| { |
| vector<const char*> enabledLayers; |
| vk::VkDeviceCreateInfo createInfo = *pCreateInfo; |
| |
| if (createInfo.enabledLayerCount == 0u && validationEnabled) |
| { |
| enabledLayers = getValidationLayers(vki, physicalDevice); |
| createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size()); |
| createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data()); |
| } |
| |
| return vki.createDevice(physicalDevice, &createInfo, pAllocator, pDevice); |
| } |
| |
| |
| } |