Add VulkanRobustness feature
Enables all supported VK_EXT_robustness2 features to avoid
emulator crashes due to invalid application behavior on the
GPU.
Bug: 389637419
Test: -feature VulkanRobustness
Change-Id: I234180352356a14210f5e1b22eebad574ea58d6a
GitOrigin-RevId: a4e88ac1f7b71a893b6d44ca519d963d980a4865
diff --git a/host/features/include/gfxstream/host/Features.h b/host/features/include/gfxstream/host/Features.h
index 6c03a70..2eaa0d2 100644
--- a/host/features/include/gfxstream/host/Features.h
+++ b/host/features/include/gfxstream/host/Features.h
@@ -221,8 +221,10 @@
};
FeatureInfo BypassVulkanDeviceFeatureOverrides = {
"BypassVulkanDeviceFeatureOverrides",
- "We are force disabling (overriding) some vulkan features (private data, uniform inline block etc) which the device may naturally support."
- "If toggled ON, this flag will cause the host side to not force disable anything and let the device fully advertise supported features.",
+ "We are force disabling (overriding) some vulkan features (private data, uniform inline "
+ "block etc) which the device may naturally support."
+ "If toggled ON, this flag will cause the host side to not force disable anything and let "
+ "the device fully advertise supported features.",
&map,
};
FeatureInfo VulkanAllocateDeviceMemoryOnly = {
@@ -321,7 +323,14 @@
"device properties for the guest queries.",
&map,
};
+ FeatureInfo VulkanRobustness = {
+ "VulkanRobustness",
+ "If enabled, robustness extensions with all supported features will be enabled on "
+ "all created devices. (e.g. VK_EXT_robustness2)",
+ &map,
+ };
};
+
struct FeatureDependencyHandler {
FeatureDependencyHandler(const FeatureSet& set) : featureSetView(set){}
const FeatureSet& featureSetView;
diff --git a/host/vulkan/VkCommonOperations.cpp b/host/vulkan/VkCommonOperations.cpp
index 3fc4f0b..42ecdd8 100644
--- a/host/vulkan/VkCommonOperations.cpp
+++ b/host/vulkan/VkCommonOperations.cpp
@@ -1220,6 +1220,15 @@
vk_append_struct(&features2Chain, &privateDataFeatures);
}
+ VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT};
+ const bool robustnessRequested = emulation->mFeatures.VulkanRobustness.enabled;
+ const bool robustnessSupported =
+ extensionsSupported(deviceExts, {VK_EXT_ROBUSTNESS_2_EXTENSION_NAME});
+ if (robustnessRequested && robustnessSupported) {
+ vk_append_struct(&features2Chain, &robustness2Features);
+ }
+
emulation->mGetPhysicalDeviceFeatures2Func(physicalDevices[i], &features2);
deviceInfos[i].supportsSamplerYcbcrConversion =
@@ -1230,6 +1239,15 @@
deviceInfos[i].supportsPrivateData = (privateDataFeatures.privateData == VK_TRUE);
+ // Enable robustness only when requested
+ if (robustnessRequested && robustnessSupported) {
+ deviceInfos[i].robustness2Features = vk_make_orphan_copy(robustness2Features);
+ } else if (robustnessRequested) {
+ WARN(
+ "VulkanRobustness was requested but the "
+ "VK_EXT_robustness2 extension is not supported.");
+ }
+
#if defined(__QNX__)
deviceInfos[i].supportsExternalMemoryImport =
extMemScreenBufferFeatures.screenBufferImport == VK_TRUE;
@@ -1358,6 +1376,10 @@
}
#endif
+ if (emulation->mDeviceInfo.robustness2Features) {
+ selectedDeviceExtensionNames_.emplace(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
+ }
+
std::vector<const char*> selectedDeviceExtensionNames(selectedDeviceExtensionNames_.begin(),
selectedDeviceExtensionNames_.end());
@@ -1422,6 +1444,14 @@
"VK_NV_device_diagnostic_checkpoints extension is not supported.");
}
+ VkPhysicalDeviceRobustness2FeaturesEXT r2features = {};
+ if (emulation->mDeviceInfo.robustness2Features) {
+ r2features = *emulation->mDeviceInfo.robustness2Features;
+ INFO("Enabling VK_EXT_robustness2 (%d %d %d).", r2features.robustBufferAccess2,
+ r2features.robustImageAccess2, r2features.nullDescriptor);
+ vk_append_struct(&deviceCiChain, &r2features);
+ }
+
ivk->vkCreateDevice(emulation->mPhysicalDevice, &dCi, nullptr, &emulation->mDevice);
if (res != VK_SUCCESS) {
@@ -1757,6 +1787,10 @@
return mDeviceInfo.supportsExternalMemoryHostProps;
}
+std::optional<VkPhysicalDeviceRobustness2FeaturesEXT> VkEmulation::getRobustness2Features() const {
+ return mDeviceInfo.robustness2Features;
+}
+
VkPhysicalDeviceExternalMemoryHostPropertiesEXT VkEmulation::externalMemoryHostProperties() const {
return mDeviceInfo.externalMemoryHostProps;
}
diff --git a/host/vulkan/VkCommonOperations.h b/host/vulkan/VkCommonOperations.h
index bb50ca3..9e14b4d 100644
--- a/host/vulkan/VkCommonOperations.h
+++ b/host/vulkan/VkCommonOperations.h
@@ -126,6 +126,8 @@
bool supportsExternalMemoryHostProperties() const;
+ std::optional<VkPhysicalDeviceRobustness2FeaturesEXT> getRobustness2Features() const;
+
VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties() const;
bool isGuestVulkanOnly() const;
@@ -472,6 +474,9 @@
#else
PFN_vkGetMemoryFdKHR getMemoryHandleFunc = nullptr;
#endif
+
+ // Set only if requested and supported
+ std::optional<VkPhysicalDeviceRobustness2FeaturesEXT> robustness2Features;
};
uint32_t getValidMemoryTypeIndex(uint32_t requiredMemoryTypeBits,
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 6bca012..2e4aca7 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -1822,6 +1822,17 @@
}
}
+ VkPhysicalDeviceRobustness2FeaturesEXT modifiedRobustness2features;
+ const auto r2features = m_vkEmulation->getRobustness2Features();
+ if (r2features && vk_find_struct<VkPhysicalDeviceRobustness2FeaturesEXT>(
+ &createInfoFiltered) == nullptr) {
+ VERBOSE("Force-enabling VK_EXT_robustness2 on device creation.");
+ updatedDeviceExtensions.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
+ modifiedRobustness2features = *r2features;
+ modifiedRobustness2features.pNext = const_cast<void*>(createInfoFiltered.pNext);
+ createInfoFiltered.pNext = &modifiedRobustness2features;
+ }
+
if (VkPhysicalDeviceFeatures2* features2 =
vk_find_struct<VkPhysicalDeviceFeatures2>(&createInfoFiltered)) {
featuresToFilter.emplace_back(&features2->features);
diff --git a/host/vulkan/cereal/common/vk_struct_id.h b/host/vulkan/cereal/common/vk_struct_id.h
index 0a9fb23..65f428b 100644
--- a/host/vulkan/cereal/common/vk_struct_id.h
+++ b/host/vulkan/cereal/common/vk_struct_id.h
@@ -105,6 +105,8 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES);
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceInlineUniformBlockFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES);
+REGISTER_VK_STRUCT_ID(VkPhysicalDeviceRobustness2FeaturesEXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT);
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX,