问题描述
我不了解Vulkan扩展系统的行为以及加载/不加载其中的某些功能,可以请有人向我解释为什么,当我拥有这些必需的扩展时:
settings.requiredInstanceExtensions.insert(
settings.requiredInstanceExtensions.end(),{
VK_KHR_SURFACE_EXTENSION_NAME,VK_KHR_disPLAY_EXTENSION_NAME,VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME
}
);
settings.requiredDeviceExtensions.insert(
settings.requiredDeviceExtensions.end(),{
VK_KHR_SWAPCHAIN_EXTENSION_NAME,VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME
}
);
我只是在实例创建过程中检查扩展的存在:
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(_validation.getValidationLayersCount());
createInfo.ppEnabledLayerNames = _validation.getValidationLayersNames();
_settings.requiredInstanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
/// Check for available extensions.
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr,&extensionCount,nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr,availableExtensions.data());
cerrlog.debug() << "Available extensions: " << std::endl;
for(const auto& extension : availableExtensions) {
cerrlog.debug() << extension.extensionName << std::endl;
}
createInfo.enabledExtensionCount = static_cast<uint32_t>(_settings.requiredInstanceExtensions.size());
createInfo.ppEnabledExtensionNames = _settings.requiredInstanceExtensions.data();
VkResult result = vkCreateInstance(&createInfo,nullptr,&_instance);
VulkanException::throwIfNotOK("Failed to create vk instance!",result);
以类似的方式,我检查扩展支持中的设备扩展,然后创建它:
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.queueCreateInfoCount = static_cast<int>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = static_cast<uint32_t>(_deviceExtensions.size());
createInfo.ppEnabledExtensionNames = _deviceExtensions.data();
if (validationEnabled) {
createInfo.enabledLayerCount = static_cast<uint32_t>(
validationLayers.getValidationLayersCount());
createInfo.ppEnabledLayerNames = validationLayers.getValidationLayersNames();
} else {
createInfo.enabledLayerCount = 0;
}
VkResult result = vkCreateDevice(_physicalDevice,&createInfo,&_device);
这将导致实例的创建,并且还将通过该实例映射vulkan核心调用(即使是从实例映射的设备也是如此)。但是我仍然需要加载调试工具:
VkResult VulkanDebugLogger::CreateDebugUtilsMessengerEXT(
VkInstance instance,const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,const VkAllocationCallbacks* pAllocator,VkDebugUtilsMessengerEXT* pCallback
)
{
auto func = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
vkGetInstanceProcAddr(instance,"vkCreateDebugUtilsMessengerEXT")
);
if (func != nullptr) {
return func(instance,pCreateInfo,pAllocator,pCallback);
}
else {
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
我还需要加载这些扩展名:
void VulkanRenderer::loadExtensions()
{
vkGetMemoryWin32HandleKHR = PFN_vkGetMemoryWin32HandleKHR(vkGetInstanceProcAddr(
_instance,"vkGetMemoryWin32HandleKHR"
));
vkGetSemaphoreWin32HandleKHR = PFN_vkGetSemaphoreWin32HandleKHR(vkGetInstanceProcAddr(
_instance,"vkGetSemaphoreWin32HandleKHR"
));
}
由于这些扩展的内容不是vulkan核心,因此必须手动加载-据我了解加载过程。但是,为什么我不需要对其余必需的扩展名做同样的事情? 即:
- VK_KHR_SURFACE_EXTENSION_NAME
- VK_KHR_disPLAY_EXTENSION_NAME
- VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
- VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
- VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME
- VK_KHR_SWAPCHAIN_EXTENSION_NAME
- VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME
- VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME
我了解这最后两个可能是相同的,但是特定于操作系统,所以我不需要加载其他两个,因为我是手动加载它们的win32版本的
- VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME
- VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME
长话短说:
1。 我不明白为什么与vkdisplay和vkSwapChain相关的方法调用对我来说非常理想,而无需通过vkGetProcAdress手动映射它们。
OR
2。 为什么我需要手动加载:
PFN_vkGetSomeExtensionKHR = vkGetInstanceProcAddr(instance,“ vkCreateDebugUtilsMessengerEXT”) vkGetInstanceProcAddr(_instance,“ vkGetMemoryWin32HandleKHR”) vkGetInstanceProcAddr(_instance,“ vkGetSemaphoreWin32HandleKHR”)
而且这些也不会自动加载...有人可以向我解释在Vulkan中加载扩展程序时必要步骤的不一致吗?
解决方法
保证来自LoaderAndLayerInterface.md文档:
Windows,Linux,Android和macOS上的加载程序库将导出所有核心Vulkan和所有适当的Window System Interface(WSI)扩展。这样做是为了简化Vulkan开发入门。
否则,加载程序可能会或可能不会导出其他扩展命令。
鉴于新版本的Vulkan进行了扩展,并且基本上将其接受到原始的Vulkan中,那么那些原始扩展命令也可能会被导出。 (例如VK_KHR_get_physical_device_properties2
现在是Vulkan 1.1的一部分。)但是我认为不能保证这些命令的导出,您还是应该手动加载它们。