【发布时间】:2020-11-04 16:34:24
【问题描述】:
我不了解 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, &extensionCount, 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, nullptr, &_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 手动映射它们......
或
2. 为什么我需要手动加载:
PFN_vkGetSomeExtensionKHR = vkGetInstanceProcAddr(instance,"vkCreateDebugUtilsMessengerEXT") vkGetInstanceProcAddr(_instance,"vkGetMemoryWin32HandleKHR") vkGetInstanceProcAddr(_instance,"vkGetSemaphoreWin32HandleKHR")
这些也不会自动加载...有人可以解释一下在 Vulkan 中加载扩展时必要步骤的不一致吗?
【问题讨论】:
标签: vulkan