Skip to content

Commit 13205b9

Browse files
ShabbyXCommit Bot
authored andcommitted
Vulkan: Cleanup device feature query and enabling
All device extension features and properties queries are now performed in a single call for each (i.e. one for features, one for properties), with all the extension structs chained. Then based on which feature is present (not just whether the extension is supported), the extensions and features are enabled. In the process, it fixes the following issues: - If VK_EXT_vertex_attribute_divisor is present, but the necessary vertexAttributeInstanceRateDivisor feature is not supported, that feature is not enabled and the emulation path is taken. Incidentally, this also fixes an issue with renderdoc that refuses to replay captures on such devices. - If VK_EXT_transform_feedback is present, but the necessary transformFeedback feature is not supported, similarly that feature is not enabled and the emulation path is taken. Bug: angleproject:4306 Bug: angleproject:4027 Change-Id: I0969064cba811d215c37dfe551b0ceedb334051c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2005111 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tobin Ehlis <tobine@google.com>
1 parent 3b2780e commit 13205b9

File tree

3 files changed

+125
-95
lines changed

3 files changed

+125
-95
lines changed

src/libANGLE/renderer/vulkan/RendererVk.cpp

Lines changed: 113 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,6 @@ RendererVk::RendererVk()
545545
mDebugUtilsMessenger(VK_NULL_HANDLE),
546546
mDebugReportCallback(VK_NULL_HANDLE),
547547
mPhysicalDevice(VK_NULL_HANDLE),
548-
mPhysicalDeviceSubgroupProperties{},
549548
mQueue(VK_NULL_HANDLE),
550549
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
551550
mMaxVertexAttribDivisor(1),
@@ -558,8 +557,6 @@ RendererVk::RendererVk()
558557
mPipelineCacheDirty(false),
559558
mPipelineCacheInitialized(false)
560559
{
561-
mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
562-
563560
VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
564561
mFormatProperties.fill(invalid);
565562
}
@@ -891,6 +888,84 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
891888
return angle::Result::Continue;
892889
}
893890

891+
void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExtensionNames)
892+
{
893+
// Default initialize all extension features to false.
894+
mLineRasterizationFeatures = {};
895+
mLineRasterizationFeatures.sType =
896+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
897+
898+
mProvokingVertexFeatures = {};
899+
mProvokingVertexFeatures.sType =
900+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
901+
902+
mVertexAttributeDivisorFeatures = {};
903+
mVertexAttributeDivisorFeatures.sType =
904+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
905+
906+
mVertexAttributeDivisorProperties = {};
907+
mVertexAttributeDivisorProperties.sType =
908+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
909+
910+
mTransformFeedbackFeatures = {};
911+
mTransformFeedbackFeatures.sType =
912+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
913+
914+
mPhysicalDeviceSubgroupProperties = {};
915+
mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
916+
917+
if (!vkGetPhysicalDeviceProperties2KHR || !vkGetPhysicalDeviceFeatures2KHR)
918+
{
919+
return;
920+
}
921+
922+
// Query features and properties.
923+
VkPhysicalDeviceFeatures2KHR deviceFeatures = {};
924+
deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
925+
926+
VkPhysicalDeviceProperties2 deviceProperties = {};
927+
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
928+
929+
// Query line rasterization features
930+
if (ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
931+
{
932+
vk::AddToPNextChain(&deviceFeatures, &mLineRasterizationFeatures);
933+
}
934+
935+
// Query provoking vertex features
936+
if (ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
937+
{
938+
vk::AddToPNextChain(&deviceFeatures, &mProvokingVertexFeatures);
939+
}
940+
941+
// Query attribute divisor features and properties
942+
if (ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
943+
{
944+
vk::AddToPNextChain(&deviceFeatures, &mVertexAttributeDivisorFeatures);
945+
vk::AddToPNextChain(&deviceProperties, &mVertexAttributeDivisorProperties);
946+
}
947+
948+
// Query transform feedback features
949+
if (ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames))
950+
{
951+
vk::AddToPNextChain(&deviceFeatures, &mTransformFeedbackFeatures);
952+
}
953+
954+
// Query subgroup properties
955+
vk::AddToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
956+
957+
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &deviceFeatures);
958+
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
959+
960+
// Clean up pNext chains
961+
mLineRasterizationFeatures.pNext = nullptr;
962+
mProvokingVertexFeatures.pNext = nullptr;
963+
mVertexAttributeDivisorFeatures.pNext = nullptr;
964+
mVertexAttributeDivisorProperties.pNext = nullptr;
965+
mTransformFeedbackFeatures.pNext = nullptr;
966+
mPhysicalDeviceSubgroupProperties.pNext = nullptr;
967+
}
968+
894969
angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
895970
{
896971
uint32_t deviceLayerCount = 0;
@@ -967,50 +1042,10 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
9671042
queueCreateInfo.queueCount = 1;
9681043
queueCreateInfo.pQueuePriorities = &zeroPriority;
9691044

970-
// Setup device initialization struct
971-
VkDeviceCreateInfo createInfo = {};
972-
973-
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
974-
createInfo.flags = 0;
975-
createInfo.queueCreateInfoCount = 1;
976-
createInfo.pQueueCreateInfos = &queueCreateInfo;
977-
createInfo.enabledLayerCount = static_cast<uint32_t>(enabledDeviceLayerNames.size());
978-
createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
979-
980-
mLineRasterizationFeatures = {};
981-
mLineRasterizationFeatures.sType =
982-
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
983-
ASSERT(mLineRasterizationFeatures.bresenhamLines == VK_FALSE);
984-
if (vkGetPhysicalDeviceFeatures2KHR &&
985-
ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
986-
{
987-
enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
988-
// Query line rasterization capabilities
989-
VkPhysicalDeviceFeatures2KHR availableFeatures = {};
990-
availableFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
991-
vk::AppendToPNextChain(&availableFeatures, &mLineRasterizationFeatures);
992-
993-
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &availableFeatures);
994-
vk::AppendToPNextChain(&createInfo, &mLineRasterizationFeatures);
995-
}
996-
997-
mProvokingVertexFeatures = {};
998-
mProvokingVertexFeatures.sType =
999-
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
1000-
ASSERT(mProvokingVertexFeatures.provokingVertexLast == VK_FALSE);
1001-
if (vkGetPhysicalDeviceFeatures2KHR &&
1002-
ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
1003-
{
1004-
enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
1005-
// Query line rasterization capabilities
1006-
VkPhysicalDeviceFeatures2KHR availableFeatures = {};
1007-
availableFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1008-
vk::AppendToPNextChain(&availableFeatures, &mProvokingVertexFeatures);
1009-
1010-
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &availableFeatures);
1011-
vk::AppendToPNextChain(&createInfo, &mProvokingVertexFeatures);
1012-
}
1045+
// Query extensions and their features.
1046+
queryDeviceExtensionFeatures(deviceExtensionNames);
10131047

1048+
// Initialize features and workarounds.
10141049
if (!displayVk->getState().featuresAllDisabled)
10151050
{
10161051
initFeatures(deviceExtensionNames);
@@ -1088,61 +1123,53 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
10881123
enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
10891124
}
10901125

1091-
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT divisorFeatures = {};
1092-
divisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
1093-
if (vkGetPhysicalDeviceProperties2KHR &&
1094-
ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
1095-
{
1096-
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1097-
divisorFeatures.vertexAttributeInstanceRateDivisor = true;
1098-
vk::AppendToPNextChain(&enabledFeatures, &divisorFeatures);
1099-
1100-
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT divisorProperties = {};
1101-
divisorProperties.sType =
1102-
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
1126+
// Setup device initialization struct
1127+
VkDeviceCreateInfo createInfo = {};
11031128

1104-
VkPhysicalDeviceProperties2 deviceProperties = {};
1105-
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1106-
vk::AppendToPNextChain(&deviceProperties, &divisorProperties);
1129+
// Based on available extension features, decide on which extensions and features to enable.
11071130

1108-
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
1109-
// We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
1110-
// exceeded
1111-
mMaxVertexAttribDivisor =
1112-
std::min(divisorProperties.maxVertexAttribDivisor,
1113-
static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
1114-
vk::AppendToPNextChain(&createInfo, &enabledFeatures);
1131+
if (mLineRasterizationFeatures.bresenhamLines)
1132+
{
1133+
enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
1134+
vk::AddToPNextChain(&createInfo, &mLineRasterizationFeatures);
11151135
}
1116-
else
1136+
1137+
if (mProvokingVertexFeatures.provokingVertexLast)
11171138
{
1118-
// Enable all available features
1119-
createInfo.pEnabledFeatures = &enabledFeatures.features;
1139+
enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
1140+
vk::AddToPNextChain(&createInfo, &mProvokingVertexFeatures);
11201141
}
11211142

1122-
if (vkGetPhysicalDeviceProperties2KHR)
1143+
if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
11231144
{
1124-
VkPhysicalDeviceProperties2 deviceProperties = {};
1125-
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1126-
vk::AppendToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
1145+
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1146+
vk::AddToPNextChain(&createInfo, &mVertexAttributeDivisorFeatures);
11271147

1128-
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
1148+
// We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
1149+
// exceeded
1150+
mMaxVertexAttribDivisor =
1151+
std::min(mVertexAttributeDivisorProperties.maxVertexAttribDivisor,
1152+
static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
11291153
}
11301154

1131-
bool supportsTransformFeedbackExt = getFeatures().supportsTransformFeedbackExtension.enabled;
1132-
if (supportsTransformFeedbackExt)
1155+
if (getFeatures().supportsTransformFeedbackExtension.enabled)
11331156
{
11341157
enabledDeviceExtensions.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
1135-
1136-
VkPhysicalDeviceTransformFeedbackFeaturesEXT xfbFeature = {};
1137-
xfbFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
1138-
xfbFeature.transformFeedback = true;
1139-
xfbFeature.geometryStreams = true;
1140-
vk::AppendToPNextChain(&enabledFeatures, &xfbFeature);
1158+
vk::AddToPNextChain(&createInfo, &mTransformFeedbackFeatures);
11411159
}
11421160

1161+
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1162+
createInfo.flags = 0;
1163+
createInfo.queueCreateInfoCount = 1;
1164+
createInfo.pQueueCreateInfos = &queueCreateInfo;
1165+
createInfo.enabledLayerCount = static_cast<uint32_t>(enabledDeviceLayerNames.size());
1166+
createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
11431167
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
11441168
createInfo.ppEnabledExtensionNames =
11451169
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
1170+
// Enable core features without assuming VkPhysicalDeviceFeatures2KHR is accepted in the pNext
1171+
// chain of VkDeviceCreateInfo.
1172+
createInfo.pEnabledFeatures = &enabledFeatures.features;
11461173

11471174
ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
11481175
volkLoadDevice(mDevice);
@@ -1437,9 +1464,8 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
14371464
(&mFeatures), supportsShaderStencilExport,
14381465
ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
14391466

1440-
ANGLE_FEATURE_CONDITION(
1441-
(&mFeatures), supportsTransformFeedbackExtension,
1442-
ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames));
1467+
ANGLE_FEATURE_CONDITION((&mFeatures), supportsTransformFeedbackExtension,
1468+
mTransformFeedbackFeatures.transformFeedback == VK_TRUE);
14431469

14441470
ANGLE_FEATURE_CONDITION((&mFeatures), emulateTransformFeedback,
14451471
(mFeatures.supportsTransformFeedbackExtension.enabled == VK_FALSE &&

src/libANGLE/renderer/vulkan/RendererVk.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class RendererVk : angle::NonCopyable
220220
angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
221221
void ensureCapsInitialized() const;
222222

223+
void queryDeviceExtensionFeatures(const ExtensionNameList &deviceExtensionNames);
224+
223225
void initFeatures(const ExtensionNameList &extensions);
224226
void initPipelineCacheVkKey();
225227
angle::Result initPipelineCache(DisplayVk *display,
@@ -252,10 +254,13 @@ class RendererVk : angle::NonCopyable
252254
VkDebugReportCallbackEXT mDebugReportCallback;
253255
VkPhysicalDevice mPhysicalDevice;
254256
VkPhysicalDeviceProperties mPhysicalDeviceProperties;
255-
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
256257
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
257258
VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
258259
VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
260+
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
261+
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
262+
VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
263+
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
259264
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
260265
std::mutex mQueueMutex;
261266
VkQueue mQueue;

src/libANGLE/renderer/vulkan/vk_utils.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,15 @@ namespace vk
103103
{
104104
struct Format;
105105

106-
// Append ptr to end of pNext chain beginning at chainStart
106+
// Prepend ptr to the pNext chain at chainStart
107107
template <typename VulkanStruct1, typename VulkanStruct2>
108-
void AppendToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr)
108+
void AddToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr)
109109
{
110+
ASSERT(ptr->pNext == nullptr);
111+
110112
VkBaseOutStructure *localPtr = reinterpret_cast<VkBaseOutStructure *>(chainStart);
111-
while (localPtr->pNext)
112-
{
113-
localPtr = localPtr->pNext;
114-
}
115-
localPtr->pNext = reinterpret_cast<VkBaseOutStructure *>(ptr);
113+
ptr->pNext = localPtr->pNext;
114+
localPtr->pNext = reinterpret_cast<VkBaseOutStructure *>(ptr);
116115
}
117116

118117
extern const char *gLoaderLayersPathEnv;

0 commit comments

Comments
 (0)