Vulkan: handle Device extensions more programmatically

Similarly to the CL for Instance extensions, it makes each device
extension linked to an enum class and a bitset. Logic surrounding device
extensions is changed to take advantage of this to be more programmatic
and less error prone when adding support for a new extension.

Bug: dawn:457
Change-Id: Iecf623c40b890b7e00ba972d5eac0712866692b5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22941
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-06-11 17:35:26 +00:00 committed by Commit Bot service account
parent 2532a718c5
commit 265fb062be
13 changed files with 285 additions and 234 deletions

View File

@ -39,7 +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.HasExt(DeviceExt::Maintenance1)) {
return DAWN_INTERNAL_ERROR( return DAWN_INTERNAL_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");
@ -74,9 +74,9 @@ namespace dawn_native { namespace vulkan {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC); mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
} }
if (mDeviceInfo.shaderFloat16Int8 && if (mDeviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE && mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
mDeviceInfo._16BitStorage && mDeviceInfo.HasExt(DeviceExt::_16BitStorage) &&
mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE) { mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE) {
mSupportedExtensions.EnableExtension(Extension::ShaderFloat16); mSupportedExtensions.EnableExtension(Extension::ShaderFloat16);
} }

View File

@ -665,7 +665,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::InsertDebugMarker: { case Command::InsertDebugMarker: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>(); InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1); const char* label = mCommands.NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo; VkDebugMarkerMarkerInfoEXT markerInfo;
@ -685,7 +685,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::PopDebugGroup: { case Command::PopDebugGroup: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
mCommands.NextCommand<PopDebugGroupCmd>(); mCommands.NextCommand<PopDebugGroupCmd>();
device->fn.CmdDebugMarkerEndEXT(commands); device->fn.CmdDebugMarkerEndEXT(commands);
} else { } else {
@ -695,7 +695,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::PushDebugGroup: { case Command::PushDebugGroup: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>(); PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1); const char* label = mCommands.NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo; VkDebugMarkerMarkerInfoEXT markerInfo;
@ -812,7 +812,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::InsertDebugMarker: { case Command::InsertDebugMarker: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>(); InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
const char* label = iter->NextData<char>(cmd->length + 1); const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo; VkDebugMarkerMarkerInfoEXT markerInfo;
@ -832,7 +832,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::PopDebugGroup: { case Command::PopDebugGroup: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
iter->NextCommand<PopDebugGroupCmd>(); iter->NextCommand<PopDebugGroupCmd>();
device->fn.CmdDebugMarkerEndEXT(commands); device->fn.CmdDebugMarkerEndEXT(commands);
} else { } else {
@ -842,7 +842,7 @@ namespace dawn_native { namespace vulkan {
} }
case Command::PushDebugGroup: { case Command::PushDebugGroup: {
if (device->GetDeviceInfo().debugMarker) { if (device->GetDeviceInfo().HasExt(DeviceExt::DebugMarker)) {
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>(); PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
const char* label = iter->NextData<char>(cmd->length + 1); const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo; VkDebugMarkerMarkerInfoEXT markerInfo;

View File

@ -268,54 +268,17 @@ namespace dawn_native { namespace vulkan {
ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) { ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) {
VulkanDeviceKnobs usedKnobs = {}; VulkanDeviceKnobs usedKnobs = {};
float zero = 0.0f; // Default to asking for all avilable known extensions.
std::vector<const char*> layersToRequest; usedKnobs.extensions = mDeviceInfo.extensions;
std::vector<const char*> extensionsToRequest;
std::vector<VkDeviceQueueCreateInfo> queuesToRequest;
if (mDeviceInfo.debugMarker) { // However only request the extensions that haven't been promoted in the device's apiVersion
extensionsToRequest.push_back(kExtensionNameExtDebugMarker); std::vector<const char*> extensionNames;
usedKnobs.debugMarker = true; for (uint32_t ext : IterateBitSet(usedKnobs.extensions.extensionBitSet)) {
} const DeviceExtInfo& info = GetDeviceExtInfo(static_cast<DeviceExt>(ext));
if (mDeviceInfo.externalMemory) {
extensionsToRequest.push_back(kExtensionNameKhrExternalMemory); if (info.versionPromoted > mDeviceInfo.properties.apiVersion) {
usedKnobs.externalMemory = true; extensionNames.push_back(info.name);
} }
if (mDeviceInfo.externalMemoryFD) {
extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryFD);
usedKnobs.externalMemoryFD = true;
}
if (mDeviceInfo.externalMemoryDmaBuf) {
extensionsToRequest.push_back(kExtensionNameExtExternalMemoryDmaBuf);
usedKnobs.externalMemoryDmaBuf = true;
}
if (mDeviceInfo.imageDrmFormatModifier) {
extensionsToRequest.push_back(kExtensionNameExtImageDrmFormatModifier);
usedKnobs.imageDrmFormatModifier = true;
}
if (mDeviceInfo.externalMemoryZirconHandle) {
extensionsToRequest.push_back(kExtensionNameFuchsiaExternalMemory);
usedKnobs.externalMemoryZirconHandle = true;
}
if (mDeviceInfo.externalSemaphore) {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphore);
usedKnobs.externalSemaphore = true;
}
if (mDeviceInfo.externalSemaphoreFD) {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreFD);
usedKnobs.externalSemaphoreFD = true;
}
if (mDeviceInfo.externalSemaphoreZirconHandle) {
extensionsToRequest.push_back(kExtensionNameFuchsiaExternalSemaphore);
usedKnobs.externalSemaphoreZirconHandle = true;
}
if (mDeviceInfo.swapchain) {
extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
usedKnobs.swapchain = true;
}
if (mDeviceInfo.maintenance1) {
extensionsToRequest.push_back(kExtensionNameKhrMaintenance1);
usedKnobs.maintenance1 = true;
} }
// Always require independentBlend because it is a core Dawn feature // Always require independentBlend because it is a core Dawn feature
@ -333,21 +296,13 @@ namespace dawn_native { namespace vulkan {
if (IsExtensionEnabled(Extension::ShaderFloat16)) { if (IsExtensionEnabled(Extension::ShaderFloat16)) {
const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo(); const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
ASSERT(deviceInfo.shaderFloat16Int8 && ASSERT(deviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
deviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE && deviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
deviceInfo._16BitStorage && deviceInfo.HasExt(DeviceExt::_16BitStorage) &&
deviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE); deviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE);
usedKnobs.shaderFloat16Int8 = true;
usedKnobs.shaderFloat16Int8Features.shaderFloat16 = VK_TRUE; usedKnobs.shaderFloat16Int8Features.shaderFloat16 = VK_TRUE;
extensionsToRequest.push_back(kExtensionNameKhrShaderFloat16Int8);
usedKnobs._16BitStorage = true;
usedKnobs._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess = VK_TRUE; usedKnobs._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess = VK_TRUE;
// VK_KHR_16bit_storage is promoted to Vulkan 1.1.
if (deviceInfo.properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
extensionsToRequest.push_back(kExtensionNameKhr16BitStorage);
}
} }
// Find a universal queue family // Find a universal queue family
@ -370,6 +325,8 @@ namespace dawn_native { namespace vulkan {
} }
// Choose to create a single universal queue // Choose to create a single universal queue
std::vector<VkDeviceQueueCreateInfo> queuesToRequest;
float zero = 0.0f;
{ {
VkDeviceQueueCreateInfo queueCreateInfo; VkDeviceQueueCreateInfo queueCreateInfo;
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@ -388,10 +345,10 @@ namespace dawn_native { namespace vulkan {
createInfo.flags = 0; createInfo.flags = 0;
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queuesToRequest.size()); createInfo.queueCreateInfoCount = static_cast<uint32_t>(queuesToRequest.size());
createInfo.pQueueCreateInfos = queuesToRequest.data(); createInfo.pQueueCreateInfos = queuesToRequest.data();
createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size()); createInfo.enabledLayerCount = 0;
createInfo.ppEnabledLayerNames = layersToRequest.data(); createInfo.ppEnabledLayerNames = nullptr;
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionNames.size());
createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); createInfo.ppEnabledExtensionNames = extensionNames.data();
createInfo.pEnabledFeatures = &usedKnobs.features; createInfo.pEnabledFeatures = &usedKnobs.features;
DAWN_TRY(CheckVkSuccess(fn.CreateDevice(physicalDevice, &createInfo, nullptr, &mVkDevice), DAWN_TRY(CheckVkSuccess(fn.CreateDevice(physicalDevice, &createInfo, nullptr, &mVkDevice),

View File

@ -23,6 +23,7 @@
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
static constexpr uint32_t VulkanVersion_1_1 = VK_MAKE_VERSION(1, 1, 0); static constexpr uint32_t VulkanVersion_1_1 = VK_MAKE_VERSION(1, 1, 0);
static constexpr uint32_t VulkanVersion_1_2 = VK_MAKE_VERSION(1, 2, 0);
static constexpr uint32_t NeverPromoted = std::numeric_limits<uint32_t>::max(); static constexpr uint32_t NeverPromoted = std::numeric_limits<uint32_t>::max();
// A static array for InstanceExtInfo that can be indexed with InstanceExts. // A static array for InstanceExtInfo that can be indexed with InstanceExts.
@ -132,4 +133,154 @@ namespace dawn_native { namespace vulkan {
} }
} }
static constexpr size_t kDeviceExtCount = static_cast<size_t>(DeviceExt::EnumCount);
static constexpr std::array<DeviceExtInfo, kDeviceExtCount> sDeviceExtInfos{{
//
{DeviceExt::Maintenance1, "VK_KHR_maintenance1", VulkanVersion_1_1},
{DeviceExt::ExternalMemory, "VK_KHR_external_memory", VulkanVersion_1_1},
{DeviceExt::ExternalSemaphore, "VK_KHR_external_semaphore", VulkanVersion_1_1},
{DeviceExt::_16BitStorage, "VK_KHR_16bit_storage", VulkanVersion_1_1},
{DeviceExt::ShaderFloat16Int8, "VK_KHR_shader_float16_int8", VulkanVersion_1_2},
{DeviceExt::ExternalMemoryFD, "VK_KHR_external_memory_fd", NeverPromoted},
{DeviceExt::ExternalMemoryDmaBuf, "VK_EXT_external_memory_dma_buf", NeverPromoted},
{DeviceExt::ExternalMemoryZirconHandle, "VK_FUCHSIA_external_memory", NeverPromoted},
{DeviceExt::ExternalSemaphoreFD, "VK_KHR_external_semaphore_fd", NeverPromoted},
{DeviceExt::ExternalSemaphoreZirconHandle, "VK_FUCHSIA_external_semaphore", NeverPromoted},
{DeviceExt::DebugMarker, "VK_EXT_debug_marker", NeverPromoted},
{DeviceExt::ImageDrmFormatModifier, "VK_EXT_image_drm_format_modifier", NeverPromoted},
{DeviceExt::Swapchain, "VK_KHR_swapchain", NeverPromoted},
//
}};
void DeviceExtSet::Set(DeviceExt extension, bool enabled) {
extensionBitSet.set(static_cast<uint32_t>(extension), enabled);
}
bool DeviceExtSet::Has(DeviceExt extension) const {
return extensionBitSet[static_cast<uint32_t>(extension)];
}
const DeviceExtInfo& GetDeviceExtInfo(DeviceExt ext) {
uint32_t index = static_cast<uint32_t>(ext);
ASSERT(index < sDeviceExtInfos.size());
ASSERT(sDeviceExtInfos[index].index == ext);
return sDeviceExtInfos[index];
}
std::unordered_map<std::string, DeviceExt> CreateDeviceExtNameMap() {
std::unordered_map<std::string, DeviceExt> result;
for (const DeviceExtInfo& info : sDeviceExtInfos) {
result[info.name] = info.index;
}
return result;
}
DeviceExtSet EnsureDependencies(const DeviceExtSet& advertisedExts,
const InstanceExtSet& instanceExts) {
// This is very similar to EnsureDependencies for instanceExtSet. See comment there for
// an explanation of what happens.
DeviceExtSet visitedSet;
DeviceExtSet trimmedSet;
auto HasDep = [&](DeviceExt ext) -> bool {
ASSERT(visitedSet.Has(ext));
return trimmedSet.Has(ext);
};
for (uint32_t i = 0; i < sDeviceExtInfos.size(); i++) {
DeviceExt ext = static_cast<DeviceExt>(i);
bool hasDependencies = false;
switch (ext) {
case DeviceExt::DebugMarker:
// TODO(cwallez@chromium.org): VK_KHR_debug_report is deprecated, switch to
// using VK_KHR_debug_utils instead.
hasDependencies = instanceExts.Has(InstanceExt::DebugReport);
break;
case DeviceExt::ImageDrmFormatModifier:
// TODO(cwallez@chromium.org): ImageDrmFormatModifier actually requires:
// - VK_KHR_bind_memory2
// - VK_KHR_image_format_list
// - VK_KHR_sampler_ycbcr_conversion
//
// Also switch to using DeviceExt::GetPhysicalDeviceProperties2 when we decouple
// Instance / Device physical device extensions.
hasDependencies = instanceExts.Has(InstanceExt::GetPhysicalDeviceProperties2);
break;
case DeviceExt::Swapchain:
hasDependencies = instanceExts.Has(InstanceExt::Surface);
break;
case DeviceExt::Maintenance1:
hasDependencies = true;
break;
case DeviceExt::ShaderFloat16Int8:
// TODO(cwallez@chromium.org): switch to using
// DeviceExt::GetPhysicalDeviceProperties2 when we decouple Instance / Device
// physical device extensions.
hasDependencies = instanceExts.Has(InstanceExt::GetPhysicalDeviceProperties2);
break;
case DeviceExt::ExternalMemory:
// TODO(cwallez@chromium.org): switch to using
// DeviceExt::ExternalMemoryCapabilities when we decouple Instance / Device
// physical device extensions.
hasDependencies = instanceExts.Has(InstanceExt::ExternalMemoryCapabilities);
break;
case DeviceExt::ExternalSemaphore:
// TODO(cwallez@chromium.org): switch to using
// DeviceExt::ExternalSemaphoreCapabilities when we decouple Instance / Device
// physical device extensions.
hasDependencies = instanceExts.Has(InstanceExt::ExternalSemaphoreCapabilities);
break;
case DeviceExt::_16BitStorage:
// TODO(cwallez@chromium.org): switch to using
// DeviceExt::GetPhysicalDeviceProperties2 when we decouple Instance / Device
// physical device extensions.
// Also depends on VK_KHR_storage_buffer_storage_class
hasDependencies = instanceExts.Has(InstanceExt::GetPhysicalDeviceProperties2);
break;
case DeviceExt::ExternalMemoryFD:
case DeviceExt::ExternalMemoryZirconHandle:
hasDependencies = HasDep(DeviceExt::ExternalMemory);
break;
case DeviceExt::ExternalMemoryDmaBuf:
hasDependencies = HasDep(DeviceExt::ExternalMemoryFD);
break;
case DeviceExt::ExternalSemaphoreFD:
case DeviceExt::ExternalSemaphoreZirconHandle:
hasDependencies = HasDep(DeviceExt::ExternalSemaphore);
break;
default:
UNREACHABLE();
break;
}
trimmedSet.Set(ext, hasDependencies && advertisedExts.Has(ext));
visitedSet.Set(ext, true);
}
return trimmedSet;
}
void MarkPromotedExtensions(DeviceExtSet* extensions, uint32_t version) {
for (const DeviceExtInfo& info : sDeviceExtInfos) {
if (info.versionPromoted <= version) {
extensions->Set(info.index, true);
}
}
}
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -70,6 +70,62 @@ namespace dawn_native { namespace vulkan {
// extensions that don't have all their transitive dependencies in advertisedExts. // extensions that don't have all their transitive dependencies in advertisedExts.
InstanceExtSet EnsureDependencies(const InstanceExtSet& advertisedExts); InstanceExtSet EnsureDependencies(const InstanceExtSet& advertisedExts);
// The list of known device extensions. They must be in dependency order (this is checked
// inside EnsureDependencies)
enum class DeviceExt {
// Promoted to 1.1
Maintenance1,
ExternalMemory,
ExternalSemaphore,
_16BitStorage,
// Promoted to 1.2
ShaderFloat16Int8,
// External* extensions
ExternalMemoryFD,
ExternalMemoryDmaBuf,
ExternalMemoryZirconHandle,
ExternalSemaphoreFD,
ExternalSemaphoreZirconHandle,
// Others
DebugMarker,
ImageDrmFormatModifier,
Swapchain,
EnumCount,
};
// A bitset wrapper that is indexed with DeviceExt.
struct DeviceExtSet {
std::bitset<static_cast<size_t>(DeviceExt::EnumCount)> extensionBitSet;
void Set(DeviceExt extension, bool enabled);
bool Has(DeviceExt extension) const;
};
// A bitset wrapper that is indexed with DeviceExt.
struct DeviceExtInfo {
DeviceExt index;
const char* name;
// The version in which this extension was promoted as built with VK_MAKE_VERSION,
// or NeverPromoted if it was never promoted.
uint32_t versionPromoted;
};
// Returns the information about a known DeviceExt
const DeviceExtInfo& GetDeviceExtInfo(DeviceExt ext);
// Returns a map that maps a Vulkan extension name to its DeviceExt.
std::unordered_map<std::string, DeviceExt> CreateDeviceExtNameMap();
// Sets entries in `extensions` to true if that entry was promoted in Vulkan version `version`
void MarkPromotedExtensions(DeviceExtSet* extensions, uint32_t version);
// From a set of extensions advertised as supported by the device (or promoted), remove all
// extensions that don't have all their transitive dependencies in advertisedExts or in
// instanceExts.
DeviceExtSet EnsureDependencies(const DeviceExtSet& advertisedExts,
const InstanceExtSet& instanceExts);
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_VULKANEXTENSIONS_H_ #endif // DAWNNATIVE_VULKAN_VULKANEXTENSIONS_H_

View File

@ -278,35 +278,35 @@ namespace dawn_native { namespace vulkan {
GET_DEVICE_PROC(UpdateDescriptorSets); GET_DEVICE_PROC(UpdateDescriptorSets);
GET_DEVICE_PROC(WaitForFences); GET_DEVICE_PROC(WaitForFences);
if (deviceInfo.debugMarker) { if (deviceInfo.HasExt(DeviceExt::DebugMarker)) {
GET_DEVICE_PROC(CmdDebugMarkerBeginEXT); GET_DEVICE_PROC(CmdDebugMarkerBeginEXT);
GET_DEVICE_PROC(CmdDebugMarkerEndEXT); GET_DEVICE_PROC(CmdDebugMarkerEndEXT);
GET_DEVICE_PROC(CmdDebugMarkerInsertEXT); GET_DEVICE_PROC(CmdDebugMarkerInsertEXT);
} }
if (deviceInfo.externalMemoryFD) { if (deviceInfo.HasExt(DeviceExt::ExternalMemoryFD)) {
GET_DEVICE_PROC(GetMemoryFdKHR); GET_DEVICE_PROC(GetMemoryFdKHR);
GET_DEVICE_PROC(GetMemoryFdPropertiesKHR); GET_DEVICE_PROC(GetMemoryFdPropertiesKHR);
} }
if (deviceInfo.externalSemaphoreFD) { if (deviceInfo.HasExt(DeviceExt::ExternalSemaphoreFD)) {
GET_DEVICE_PROC(ImportSemaphoreFdKHR); GET_DEVICE_PROC(ImportSemaphoreFdKHR);
GET_DEVICE_PROC(GetSemaphoreFdKHR); GET_DEVICE_PROC(GetSemaphoreFdKHR);
} }
#if VK_USE_PLATFORM_FUCHSIA #if VK_USE_PLATFORM_FUCHSIA
if (deviceInfo.externalMemoryZirconHandle) { if (deviceInfo.HasExt(DeviceExt::ExternalMemoryZirconHandle)) {
GET_DEVICE_PROC(GetMemoryZirconHandleFUCHSIA); GET_DEVICE_PROC(GetMemoryZirconHandleFUCHSIA);
GET_DEVICE_PROC(GetMemoryZirconHandlePropertiesFUCHSIA); GET_DEVICE_PROC(GetMemoryZirconHandlePropertiesFUCHSIA);
} }
if (deviceInfo.externalSemaphoreZirconHandle) { if (deviceInfo.HasExt(DeviceExt::ExternalSemaphoreZirconHandle)) {
GET_DEVICE_PROC(ImportSemaphoreZirconHandleFUCHSIA); GET_DEVICE_PROC(ImportSemaphoreZirconHandleFUCHSIA);
GET_DEVICE_PROC(GetSemaphoreZirconHandleFUCHSIA); GET_DEVICE_PROC(GetSemaphoreZirconHandleFUCHSIA);
} }
#endif #endif
if (deviceInfo.swapchain) { if (deviceInfo.HasExt(DeviceExt::Swapchain)) {
GET_DEVICE_PROC(CreateSwapchainKHR); GET_DEVICE_PROC(CreateSwapchainKHR);
GET_DEVICE_PROC(DestroySwapchainKHR); GET_DEVICE_PROC(DestroySwapchainKHR);
GET_DEVICE_PROC(GetSwapchainImagesKHR); GET_DEVICE_PROC(GetSwapchainImagesKHR);

View File

@ -28,10 +28,6 @@ namespace dawn_native { namespace vulkan {
return strncmp(layer.layerName, name, VK_MAX_EXTENSION_NAME_SIZE) == 0; return strncmp(layer.layerName, name, VK_MAX_EXTENSION_NAME_SIZE) == 0;
} }
bool IsExtensionName(const VkExtensionProperties& extension, const char* name) {
return strncmp(extension.extensionName, name, VK_MAX_EXTENSION_NAME_SIZE) == 0;
}
bool EnumerateInstanceExtensions(const char* layerName, bool EnumerateInstanceExtensions(const char* layerName,
const dawn_native::vulkan::VulkanFunctions& vkFunctions, const dawn_native::vulkan::VulkanFunctions& vkFunctions,
std::vector<VkExtensionProperties>* extensions) { std::vector<VkExtensionProperties>* extensions) {
@ -54,30 +50,14 @@ namespace dawn_native { namespace vulkan {
const char kLayerNameRenderDocCapture[] = "VK_LAYER_RENDERDOC_Capture"; const char kLayerNameRenderDocCapture[] = "VK_LAYER_RENDERDOC_Capture";
const char kLayerNameFuchsiaImagePipeSwapchain[] = "VK_LAYER_FUCHSIA_imagepipe_swapchain"; const char kLayerNameFuchsiaImagePipeSwapchain[] = "VK_LAYER_FUCHSIA_imagepipe_swapchain";
const char kExtensionNameExtDebugMarker[] = "VK_EXT_debug_marker";
const char kExtensionNameKhrExternalMemory[] = "VK_KHR_external_memory";
const char kExtensionNameKhrExternalMemoryCapabilities[] =
"VK_KHR_external_memory_capabilities";
const char kExtensionNameKhrExternalMemoryFD[] = "VK_KHR_external_memory_fd";
const char kExtensionNameExtExternalMemoryDmaBuf[] = "VK_EXT_external_memory_dma_buf";
const char kExtensionNameExtImageDrmFormatModifier[] = "VK_EXT_image_drm_format_modifier";
const char kExtensionNameFuchsiaExternalMemory[] = "VK_FUCHSIA_external_memory";
const char kExtensionNameKhrExternalSemaphore[] = "VK_KHR_external_semaphore";
const char kExtensionNameKhrExternalSemaphoreCapabilities[] =
"VK_KHR_external_semaphore_capabilities";
const char kExtensionNameKhrExternalSemaphoreFD[] = "VK_KHR_external_semaphore_fd";
const char kExtensionNameFuchsiaExternalSemaphore[] = "VK_FUCHSIA_external_semaphore";
const char kExtensionNameKhrGetPhysicalDeviceProperties2[] =
"VK_KHR_get_physical_device_properties2";
const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain";
const char kExtensionNameKhrMaintenance1[] = "VK_KHR_maintenance1";
const char kExtensionNameKhrShaderFloat16Int8[] = "VK_KHR_shader_float16_int8";
const char kExtensionNameKhr16BitStorage[] = "VK_KHR_16bit_storage";
bool VulkanGlobalKnobs::HasExt(InstanceExt ext) const { bool VulkanGlobalKnobs::HasExt(InstanceExt ext) const {
return extensions.Has(ext); return extensions.Has(ext);
} }
bool VulkanDeviceKnobs::HasExt(DeviceExt ext) const {
return extensions.Has(ext);
}
ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend) { ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend) {
VulkanGlobalInfo info = {}; VulkanGlobalInfo info = {};
const VulkanFunctions& vkFunctions = backend.GetFunctions(); const VulkanFunctions& vkFunctions = backend.GetFunctions();
@ -248,82 +228,47 @@ namespace dawn_native { namespace vulkan {
return DAWN_INTERNAL_ERROR("vkEnumerateDeviceExtensionProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateDeviceExtensionProperties");
} }
info.extensions.resize(count); std::vector<VkExtensionProperties> extensionsProperties;
DAWN_TRY(CheckVkSuccess(vkFunctions.EnumerateDeviceExtensionProperties( extensionsProperties.resize(count);
physicalDevice, nullptr, &count, info.extensions.data()), DAWN_TRY(
"vkEnumerateDeviceExtensionProperties")); CheckVkSuccess(vkFunctions.EnumerateDeviceExtensionProperties(
physicalDevice, nullptr, &count, extensionsProperties.data()),
"vkEnumerateDeviceExtensionProperties"));
for (const auto& extension : info.extensions) { std::unordered_map<std::string, DeviceExt> knownExts = CreateDeviceExtNameMap();
if (IsExtensionName(extension, kExtensionNameExtDebugMarker)) {
info.debugMarker = true;
}
if (IsExtensionName(extension, kExtensionNameKhrExternalMemory)) {
info.externalMemory = true;
}
if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryFD)) {
info.externalMemoryFD = true;
}
if (IsExtensionName(extension, kExtensionNameExtExternalMemoryDmaBuf)) {
info.externalMemoryDmaBuf = true;
}
if (IsExtensionName(extension, kExtensionNameExtImageDrmFormatModifier)) {
info.imageDrmFormatModifier = true;
}
if (IsExtensionName(extension, kExtensionNameFuchsiaExternalMemory)) {
info.externalMemoryZirconHandle = true;
}
if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphore)) {
info.externalSemaphore = true;
}
if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreFD)) {
info.externalSemaphoreFD = true;
}
if (IsExtensionName(extension, kExtensionNameFuchsiaExternalSemaphore)) {
info.externalSemaphoreZirconHandle = true;
}
if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
info.swapchain = true;
}
if (IsExtensionName(extension, kExtensionNameKhrMaintenance1)) {
info.maintenance1 = true;
}
if (IsExtensionName(extension, kExtensionNameKhrShaderFloat16Int8) &&
globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2)) {
info.shaderFloat16Int8 = true;
info.shaderFloat16Int8Features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
VkPhysicalDeviceFeatures2KHR physicalDeviceFeatures2 = {}; for (const VkExtensionProperties& extension : extensionsProperties) {
physicalDeviceFeatures2.sType = auto it = knownExts.find(extension.extensionName);
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; if (it != knownExts.end()) {
physicalDeviceFeatures2.pNext = &info.shaderFloat16Int8Features; info.extensions.Set(it->second, true);
vkFunctions.GetPhysicalDeviceFeatures2(physicalDevice,
&physicalDeviceFeatures2);
}
if (IsExtensionName(extension, kExtensionNameKhr16BitStorage) &&
globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2)) {
info._16BitStorage = true;
} }
} }
MarkPromotedExtensions(&info.extensions, info.properties.apiVersion);
info.extensions = EnsureDependencies(info.extensions, globalInfo.extensions);
} }
// Mark the extensions promoted to Vulkan 1.1 as available. // Gather additional information for some of the extensions
if (info.properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { {
info.maintenance1 = true; if (info.extensions.Has(DeviceExt::ShaderFloat16Int8)) {
} info.shaderFloat16Int8Features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
// VK_KHR_16bit_storage is promoted to Vulkan 1.1, so gather information if either is VkPhysicalDeviceFeatures2KHR physicalDeviceFeatures2 = {};
// present, and mark the extension as available. physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
if (info._16BitStorage || info.properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { physicalDeviceFeatures2.pNext = &info.shaderFloat16Int8Features;
ASSERT(globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2)); vkFunctions.GetPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures2);
info._16BitStorage = true; }
info._16BitStorageFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 = {}; if (info.extensions.Has(DeviceExt::_16BitStorage)) {
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; info._16BitStorageFeatures.sType =
physicalDeviceFeatures2.pNext = &info._16BitStorageFeatures; VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
vkFunctions.GetPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures2);
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 = {};
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.pNext = &info._16BitStorageFeatures;
vkFunctions.GetPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures2);
}
} }
// TODO(cwallez@chromium.org): gather info about formats // TODO(cwallez@chromium.org): gather info about formats

View File

@ -31,23 +31,6 @@ namespace dawn_native { namespace vulkan {
extern const char kLayerNameRenderDocCapture[]; extern const char kLayerNameRenderDocCapture[];
extern const char kLayerNameFuchsiaImagePipeSwapchain[]; extern const char kLayerNameFuchsiaImagePipeSwapchain[];
extern const char kExtensionNameExtDebugMarker[];
extern const char kExtensionNameKhrExternalMemory[];
extern const char kExtensionNameKhrExternalMemoryCapabilities[];
extern const char kExtensionNameKhrExternalMemoryFD[];
extern const char kExtensionNameExtExternalMemoryDmaBuf[];
extern const char kExtensionNameExtImageDrmFormatModifier[];
extern const char kExtensionNameFuchsiaExternalMemory[];
extern const char kExtensionNameKhrExternalSemaphore[];
extern const char kExtensionNameKhrExternalSemaphoreCapabilities[];
extern const char kExtensionNameKhrExternalSemaphoreFD[];
extern const char kExtensionNameFuchsiaExternalSemaphore[];
extern const char kExtensionNameKhrGetPhysicalDeviceProperties2[];
extern const char kExtensionNameKhrSwapchain[];
extern const char kExtensionNameKhrMaintenance1[];
extern const char kExtensionNameKhrShaderFloat16Int8[];
extern const char kExtensionNameKhr16BitStorage[];
// Global information - gathered before the instance is created // Global information - gathered before the instance is created
struct VulkanGlobalKnobs { struct VulkanGlobalKnobs {
// Layers // Layers
@ -72,20 +55,8 @@ namespace dawn_native { namespace vulkan {
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shaderFloat16Int8Features; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shaderFloat16Int8Features;
VkPhysicalDevice16BitStorageFeaturesKHR _16BitStorageFeatures; VkPhysicalDevice16BitStorageFeaturesKHR _16BitStorageFeatures;
// Extensions, promoted extensions are set to true if their core version is supported. bool HasExt(DeviceExt ext) const;
bool debugMarker = false; DeviceExtSet extensions;
bool externalMemory = false;
bool externalMemoryFD = false;
bool externalMemoryDmaBuf = false;
bool imageDrmFormatModifier = false;
bool externalMemoryZirconHandle = false;
bool externalSemaphore = false;
bool externalSemaphoreFD = false;
bool externalSemaphoreZirconHandle = false;
bool swapchain = false;
bool maintenance1 = false;
bool shaderFloat16Int8 = false;
bool _16BitStorage = false;
}; };
struct VulkanDeviceInfo : VulkanDeviceKnobs { struct VulkanDeviceInfo : VulkanDeviceKnobs {
@ -96,7 +67,6 @@ namespace dawn_native { namespace vulkan {
std::vector<VkMemoryHeap> memoryHeaps; std::vector<VkMemoryHeap> memoryHeaps;
std::vector<VkLayerProperties> layers; std::vector<VkLayerProperties> layers;
std::vector<VkExtensionProperties> extensions;
// TODO(cwallez@chromium.org): layer instance extensions // TODO(cwallez@chromium.org): layer instance extensions
}; };

View File

@ -61,13 +61,9 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
Service::Service(Device* device) : mDevice(device) { Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo(); const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
const VulkanGlobalInfo& globalInfo =
ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
mSupported = globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2) && mSupported = deviceInfo.HasExt(DeviceExt::ExternalMemoryFD) &&
globalInfo.HasExt(InstanceExt::ExternalMemoryCapabilities) && deviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier);
deviceInfo.externalMemory && deviceInfo.externalMemoryFD &&
deviceInfo.externalMemoryDmaBuf && deviceInfo.imageDrmFormatModifier;
} }
Service::~Service() = default; Service::~Service() = default;

View File

@ -23,13 +23,7 @@
namespace dawn_native { namespace vulkan { namespace external_memory { namespace dawn_native { namespace vulkan { namespace external_memory {
Service::Service(Device* device) : mDevice(device) { Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo(); mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalMemoryFD);
const VulkanGlobalInfo& globalInfo =
ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
mSupported = globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2) &&
globalInfo.HasExt(InstanceExt::ExternalMemoryCapabilities) &&
deviceInfo.externalMemory && deviceInfo.externalMemoryFD;
} }
Service::~Service() = default; Service::~Service() = default;

View File

@ -23,13 +23,7 @@
namespace dawn_native { namespace vulkan { namespace external_memory { namespace dawn_native { namespace vulkan { namespace external_memory {
Service::Service(Device* device) : mDevice(device) { Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo(); mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalMemoryZirconHandle);
const VulkanGlobalInfo& globalInfo =
ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
mSupported = globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2) &&
globalInfo.HasExt(InstanceExt::ExternalMemoryCapabilities) &&
deviceInfo.externalMemory && deviceInfo.externalMemoryFD;
} }
Service::~Service() = default; Service::~Service() = default;

View File

@ -21,13 +21,7 @@
namespace dawn_native { namespace vulkan { namespace external_semaphore { namespace dawn_native { namespace vulkan { namespace external_semaphore {
Service::Service(Device* device) : mDevice(device) { Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo(); mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalSemaphoreFD);
const VulkanGlobalInfo& globalInfo =
ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
mSupported = globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2) &&
globalInfo.HasExt(InstanceExt::ExternalSemaphoreCapabilities) &&
deviceInfo.externalSemaphore && deviceInfo.externalSemaphoreFD;
// Early out before we try using extension functions // Early out before we try using extension functions
if (!mSupported) { if (!mSupported) {

View File

@ -21,13 +21,7 @@
namespace dawn_native { namespace vulkan { namespace external_semaphore { namespace dawn_native { namespace vulkan { namespace external_semaphore {
Service::Service(Device* device) : mDevice(device) { Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo(); mSupported = device->GetDeviceInfo().hasExt(DeviceExt::ExternalSemaphoreZirconHandle);
const VulkanGlobalInfo& globalInfo =
ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
mSupported = globalInfo.HasExt(InstanceExt::GetPhysicalDeviceProperties2) &&
globalInfo.HasExt(InstanceExt::ExternalSemaphoreCapabilities) &&
deviceInfo.externalSemaphore && deviceInfo.externalSemaphoreFD;
// Early out before we try using extension functions // Early out before we try using extension functions
if (!mSupported) { if (!mSupported) {