Vulkan: Load promoted extensions or core entrypoint as needed

Previously we would always assume that if the driver supported a Vulkan
version it would also support extensions that were promoted in that
version. This is not a spec requirement, so instead try to load the core
entrypoints, and only if the version is not available, load the
extension entrypoints.

Also renames VulkanFunction members that are from promoted extension to
not have a vendor prefix.

Also tag the promoted extensions that are the same in a core version as
available when that core version is available. This simplifies checking
for features in the Vulkan backend.

Bug:
Change-Id: I0817c01b8838ba26070858abb0cbed030e3291df
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16040
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: David Turner <digit@google.com>
This commit is contained in:
Corentin Wallez 2020-02-24 15:08:18 +00:00 committed by Commit Bot service account
parent 33466973bc
commit 1249ada986
11 changed files with 90 additions and 65 deletions

View File

@ -39,8 +39,7 @@ namespace dawn_native { namespace vulkan {
MaybeError Adapter::Initialize() { MaybeError Adapter::Initialize() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
if (!mDeviceInfo.maintenance1 && if (!mDeviceInfo.maintenance1) {
mDeviceInfo.properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
return DAWN_DEVICE_LOST_ERROR( return DAWN_DEVICE_LOST_ERROR(
"Dawn requires Vulkan 1.1 or Vulkan 1.0 with KHR_Maintenance1 in order to support " "Dawn requires Vulkan 1.1 or Vulkan 1.0 with KHR_Maintenance1 in order to support "
"viewport flipY"); "viewport flipY");

View File

@ -190,29 +190,16 @@ namespace dawn_native { namespace vulkan {
} }
} }
// Always request all extensions used to create VkSurfaceKHR objects so that they are
// always available for embedders looking to create VkSurfaceKHR on our VkInstance.
if (mGlobalInfo.fuchsiaImagePipeSwapchain) { if (mGlobalInfo.fuchsiaImagePipeSwapchain) {
layersToRequest.push_back(kLayerNameFuchsiaImagePipeSwapchain); layersToRequest.push_back(kLayerNameFuchsiaImagePipeSwapchain);
usedKnobs.fuchsiaImagePipeSwapchain = true; usedKnobs.fuchsiaImagePipeSwapchain = true;
} }
// Always request all extensions used to create VkSurfaceKHR objects so that they are
// always available for embedders looking to create VkSurfaceKHR on our VkInstance.
if (mGlobalInfo.macosSurface) { if (mGlobalInfo.macosSurface) {
extensionsToRequest.push_back(kExtensionNameMvkMacosSurface); extensionsToRequest.push_back(kExtensionNameMvkMacosSurface);
usedKnobs.macosSurface = true; usedKnobs.macosSurface = true;
} }
if (mGlobalInfo.externalMemoryCapabilities) {
extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryCapabilities);
usedKnobs.externalMemoryCapabilities = true;
}
if (mGlobalInfo.externalSemaphoreCapabilities) {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreCapabilities);
usedKnobs.externalSemaphoreCapabilities = true;
}
if (mGlobalInfo.getPhysicalDeviceProperties2) {
extensionsToRequest.push_back(kExtensionNameKhrGetPhysicalDeviceProperties2);
usedKnobs.getPhysicalDeviceProperties2 = true;
}
if (mGlobalInfo.surface) { if (mGlobalInfo.surface) {
extensionsToRequest.push_back(kExtensionNameKhrSurface); extensionsToRequest.push_back(kExtensionNameKhrSurface);
usedKnobs.surface = true; usedKnobs.surface = true;
@ -238,6 +225,28 @@ namespace dawn_native { namespace vulkan {
usedKnobs.fuchsiaImagePipeSurface = true; usedKnobs.fuchsiaImagePipeSurface = true;
} }
// Mark the promoted extensions as present if the core version in which they were promoted
// is used. This allows having a single boolean that checks if the functionality from that
// extension is available (instead of checking extension || coreVersion).
if (mGlobalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
usedKnobs.getPhysicalDeviceProperties2 = true;
usedKnobs.externalMemoryCapabilities = true;
usedKnobs.externalSemaphoreCapabilities = true;
} else {
if (mGlobalInfo.externalMemoryCapabilities) {
extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryCapabilities);
usedKnobs.externalMemoryCapabilities = true;
}
if (mGlobalInfo.externalSemaphoreCapabilities) {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreCapabilities);
usedKnobs.externalSemaphoreCapabilities = true;
}
if (mGlobalInfo.getPhysicalDeviceProperties2) {
extensionsToRequest.push_back(kExtensionNameKhrGetPhysicalDeviceProperties2);
usedKnobs.getPhysicalDeviceProperties2 = true;
}
}
VkApplicationInfo appInfo; VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pNext = nullptr; appInfo.pNext = nullptr;

View File

@ -41,12 +41,15 @@ namespace dawn_native { namespace vulkan {
return {}; return {};
} }
#define GET_INSTANCE_PROC(name) \ #define GET_INSTANCE_PROC_BASE(name, procName) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #procName)); \
if (name == nullptr) { \ if (name == nullptr) { \
return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \ return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #procName); \
} }
#define GET_INSTANCE_PROC(name) GET_INSTANCE_PROC_BASE(name, name)
#define GET_INSTANCE_PROC_VENDOR(name, vendor) GET_INSTANCE_PROC_BASE(name, name##vendor)
MaybeError VulkanFunctions::LoadInstanceProcs(VkInstance instance, MaybeError VulkanFunctions::LoadInstanceProcs(VkInstance instance,
const VulkanGlobalInfo& globalInfo) { const VulkanGlobalInfo& globalInfo) {
// Load this proc first so that we can destroy the instance even if some other // Load this proc first so that we can destroy the instance even if some other
@ -73,26 +76,36 @@ namespace dawn_native { namespace vulkan {
GET_INSTANCE_PROC(DestroyDebugReportCallbackEXT); GET_INSTANCE_PROC(DestroyDebugReportCallbackEXT);
} }
// Vulkan 1.1 is not required to report promoted extensions from 1.0 // Vulkan 1.1 is not required to report promoted extensions from 1.0 and is not required to
if (globalInfo.externalMemoryCapabilities || // support the vendor entrypoint in GetProcAddress.
globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { if (globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
GET_INSTANCE_PROC(GetPhysicalDeviceExternalBufferPropertiesKHR); GET_INSTANCE_PROC(GetPhysicalDeviceExternalBufferProperties);
} else if (globalInfo.externalMemoryCapabilities) {
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceExternalBufferProperties, KHR);
} }
if (globalInfo.externalSemaphoreCapabilities || if (globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { GET_INSTANCE_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
GET_INSTANCE_PROC(GetPhysicalDeviceExternalSemaphorePropertiesKHR); } else if (globalInfo.externalSemaphoreCapabilities) {
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceExternalSemaphoreProperties, KHR);
} }
if (globalInfo.getPhysicalDeviceProperties2 || if (globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { GET_INSTANCE_PROC(GetPhysicalDeviceFeatures2);
GET_INSTANCE_PROC(GetPhysicalDeviceFeatures2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceProperties2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceImageFormatProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceImageFormatProperties2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties2KHR); GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties2);
GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties2KHR); } else if (globalInfo.getPhysicalDeviceProperties2) {
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceFeatures2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceProperties2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceFormatProperties2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceImageFormatProperties2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceQueueFamilyProperties2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceMemoryProperties2, KHR);
GET_INSTANCE_PROC_VENDOR(GetPhysicalDeviceSparseImageFormatProperties2, KHR);
} }
if (globalInfo.surface) { if (globalInfo.surface) {

View File

@ -84,27 +84,28 @@ namespace dawn_native { namespace vulkan {
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR = PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR =
nullptr; nullptr;
// Core Vulkan 1.1 promoted extensions // Core Vulkan 1.1 promoted extensions, set if either the core version or the extension is
// present.
// VK_KHR_external_memory_capabilities // VK_KHR_external_memory_capabilities
PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
GetPhysicalDeviceExternalBufferPropertiesKHR = nullptr; nullptr;
// VK_KHR_external_semaphore_capabilities // VK_KHR_external_semaphore_capabilities
PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR PFN_vkGetPhysicalDeviceExternalSemaphoreProperties
GetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr; GetPhysicalDeviceExternalSemaphoreProperties = nullptr;
// VK_KHR_get_physical_device_properties2 // VK_KHR_get_physical_device_properties2
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR = nullptr; PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2 = nullptr;
PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR = nullptr; PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2 = nullptr;
PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR = nullptr; PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2 = nullptr;
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2 =
GetPhysicalDeviceImageFormatProperties2KHR = nullptr; nullptr;
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2 =
GetPhysicalDeviceQueueFamilyProperties2KHR = nullptr; nullptr;
PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR = nullptr; PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2 = nullptr;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR PFN_vkGetPhysicalDeviceSparseImageFormatProperties2
GetPhysicalDeviceSparseImageFormatProperties2KHR = nullptr; GetPhysicalDeviceSparseImageFormatProperties2 = nullptr;
#ifdef VK_USE_PLATFORM_FUCHSIA #ifdef VK_USE_PLATFORM_FUCHSIA
// FUCHSIA_image_pipe_surface // FUCHSIA_image_pipe_surface

View File

@ -14,6 +14,7 @@
#include "dawn_native/vulkan/VulkanInfo.h" #include "dawn_native/vulkan/VulkanInfo.h"
#include "common/Log.h"
#include "dawn_native/vulkan/AdapterVk.h" #include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BackendVk.h" #include "dawn_native/vulkan/BackendVk.h"
#include "dawn_native/vulkan/VulkanError.h" #include "dawn_native/vulkan/VulkanError.h"
@ -313,6 +314,11 @@ namespace dawn_native { namespace vulkan {
} }
} }
// Mark the extensions promoted to Vulkan 1.1 as available.
if (info.properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
info.maintenance1 = true;
}
// TODO(cwallez@chromium.org): gather info about formats // TODO(cwallez@chromium.org): gather info about formats
return info; return info;

View File

@ -86,7 +86,7 @@ namespace dawn_native { namespace vulkan {
struct VulkanDeviceKnobs { struct VulkanDeviceKnobs {
VkPhysicalDeviceFeatures features; VkPhysicalDeviceFeatures features;
// Extensions // Extensions, promoted extensions are set to true if their core version is supported.
bool debugMarker = false; bool debugMarker = false;
bool externalMemory = false; bool externalMemory = false;
bool externalMemoryFD = false; bool externalMemoryFD = false;

View File

@ -41,13 +41,13 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
formatProps.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; formatProps.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
formatProps.pNext = &formatModifierPropsList; formatProps.pNext = &formatModifierPropsList;
fn.GetPhysicalDeviceFormatProperties2KHR(physicalDevice, format, &formatProps); fn.GetPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProps);
uint32_t modifierCount = formatModifierPropsList.drmFormatModifierCount; uint32_t modifierCount = formatModifierPropsList.drmFormatModifierCount;
std::vector<VkDrmFormatModifierPropertiesEXT> formatModifierProps(modifierCount); std::vector<VkDrmFormatModifierPropertiesEXT> formatModifierProps(modifierCount);
formatModifierPropsList.pDrmFormatModifierProperties = formatModifierProps.data(); formatModifierPropsList.pDrmFormatModifierProperties = formatModifierProps.data();
fn.GetPhysicalDeviceFormatProperties2KHR(physicalDevice, format, &formatProps); fn.GetPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProps);
for (const auto& props : formatModifierProps) { for (const auto& props : formatModifierProps) {
if (props.drmFormatModifier == modifier) { if (props.drmFormatModifier == modifier) {
uint32_t count = props.drmFormatModifierPlaneCount; uint32_t count = props.drmFormatModifierPlaneCount;
@ -141,8 +141,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
imageFormatProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; imageFormatProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
imageFormatProps.pNext = &externalImageFormatProps; imageFormatProps.pNext = &externalImageFormatProps;
VkResult result = VkResult result = VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2(
VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2KHR(
physicalDevice, &imageFormatInfo, &imageFormatProps)); physicalDevice, &imageFormatInfo, &imageFormatProps));
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return false; return false;

View File

@ -66,10 +66,8 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR; formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
formatProperties.pNext = &externalFormatProperties; formatProperties.pNext = &externalFormatProperties;
VkResult result = VkResult result = VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2(
VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2KHR( ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties));
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo,
&formatProperties));
// If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED // If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {

View File

@ -66,7 +66,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR; formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
formatProperties.pNext = &externalFormatProperties; formatProperties.pNext = &externalFormatProperties;
VkResult result = mDevice->fn.GetPhysicalDeviceImageFormatProperties2KHR( VkResult result = mDevice->fn.GetPhysicalDeviceImageFormatProperties2(
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties); ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties);
// If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED // If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED

View File

@ -43,7 +43,7 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR; semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
semaphoreProperties.pNext = nullptr; semaphoreProperties.pNext = nullptr;
mDevice->fn.GetPhysicalDeviceExternalSemaphorePropertiesKHR( mDevice->fn.GetPhysicalDeviceExternalSemaphoreProperties(
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo, ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
&semaphoreProperties); &semaphoreProperties);

View File

@ -43,7 +43,7 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR; semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
semaphoreProperties.pNext = nullptr; semaphoreProperties.pNext = nullptr;
mDevice->fn.GetPhysicalDeviceExternalSemaphorePropertiesKHR( mDevice->fn.GetPhysicalDeviceExternalSemaphoreProperties(
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo, ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
&semaphoreProperties); &semaphoreProperties);