Commit 13205b93 by Shahbaz Youssefi Committed by Commit Bot

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: 's avatarTobin Ehlis <tobine@google.com>
parent 3b2780e6
......@@ -545,7 +545,6 @@ RendererVk::RendererVk()
mDebugUtilsMessenger(VK_NULL_HANDLE),
mDebugReportCallback(VK_NULL_HANDLE),
mPhysicalDevice(VK_NULL_HANDLE),
mPhysicalDeviceSubgroupProperties{},
mQueue(VK_NULL_HANDLE),
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mMaxVertexAttribDivisor(1),
......@@ -558,8 +557,6 @@ RendererVk::RendererVk()
mPipelineCacheDirty(false),
mPipelineCacheInitialized(false)
{
mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
mFormatProperties.fill(invalid);
}
......@@ -891,6 +888,84 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
return angle::Result::Continue;
}
void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExtensionNames)
{
// Default initialize all extension features to false.
mLineRasterizationFeatures = {};
mLineRasterizationFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
mProvokingVertexFeatures = {};
mProvokingVertexFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
mVertexAttributeDivisorFeatures = {};
mVertexAttributeDivisorFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
mVertexAttributeDivisorProperties = {};
mVertexAttributeDivisorProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
mTransformFeedbackFeatures = {};
mTransformFeedbackFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
mPhysicalDeviceSubgroupProperties = {};
mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
if (!vkGetPhysicalDeviceProperties2KHR || !vkGetPhysicalDeviceFeatures2KHR)
{
return;
}
// Query features and properties.
VkPhysicalDeviceFeatures2KHR deviceFeatures = {};
deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
VkPhysicalDeviceProperties2 deviceProperties = {};
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
// Query line rasterization features
if (ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mLineRasterizationFeatures);
}
// Query provoking vertex features
if (ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mProvokingVertexFeatures);
}
// Query attribute divisor features and properties
if (ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mVertexAttributeDivisorFeatures);
vk::AddToPNextChain(&deviceProperties, &mVertexAttributeDivisorProperties);
}
// Query transform feedback features
if (ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mTransformFeedbackFeatures);
}
// Query subgroup properties
vk::AddToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &deviceFeatures);
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
// Clean up pNext chains
mLineRasterizationFeatures.pNext = nullptr;
mProvokingVertexFeatures.pNext = nullptr;
mVertexAttributeDivisorFeatures.pNext = nullptr;
mVertexAttributeDivisorProperties.pNext = nullptr;
mTransformFeedbackFeatures.pNext = nullptr;
mPhysicalDeviceSubgroupProperties.pNext = nullptr;
}
angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
{
uint32_t deviceLayerCount = 0;
......@@ -967,50 +1042,10 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &zeroPriority;
// Setup device initialization struct
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.flags = 0;
createInfo.queueCreateInfoCount = 1;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(enabledDeviceLayerNames.size());
createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
mLineRasterizationFeatures = {};
mLineRasterizationFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
ASSERT(mLineRasterizationFeatures.bresenhamLines == VK_FALSE);
if (vkGetPhysicalDeviceFeatures2KHR &&
ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
{
enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
// Query line rasterization capabilities
VkPhysicalDeviceFeatures2KHR availableFeatures = {};
availableFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vk::AppendToPNextChain(&availableFeatures, &mLineRasterizationFeatures);
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &availableFeatures);
vk::AppendToPNextChain(&createInfo, &mLineRasterizationFeatures);
}
mProvokingVertexFeatures = {};
mProvokingVertexFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
ASSERT(mProvokingVertexFeatures.provokingVertexLast == VK_FALSE);
if (vkGetPhysicalDeviceFeatures2KHR &&
ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
{
enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
// Query line rasterization capabilities
VkPhysicalDeviceFeatures2KHR availableFeatures = {};
availableFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vk::AppendToPNextChain(&availableFeatures, &mProvokingVertexFeatures);
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &availableFeatures);
vk::AppendToPNextChain(&createInfo, &mProvokingVertexFeatures);
}
// Query extensions and their features.
queryDeviceExtensionFeatures(deviceExtensionNames);
// Initialize features and workarounds.
if (!displayVk->getState().featuresAllDisabled)
{
initFeatures(deviceExtensionNames);
......@@ -1088,61 +1123,53 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
}
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT divisorFeatures = {};
divisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
if (vkGetPhysicalDeviceProperties2KHR &&
ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
{
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
divisorFeatures.vertexAttributeInstanceRateDivisor = true;
vk::AppendToPNextChain(&enabledFeatures, &divisorFeatures);
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT divisorProperties = {};
divisorProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
// Setup device initialization struct
VkDeviceCreateInfo createInfo = {};
VkPhysicalDeviceProperties2 deviceProperties = {};
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
vk::AppendToPNextChain(&deviceProperties, &divisorProperties);
// Based on available extension features, decide on which extensions and features to enable.
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
// We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
// exceeded
mMaxVertexAttribDivisor =
std::min(divisorProperties.maxVertexAttribDivisor,
static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
vk::AppendToPNextChain(&createInfo, &enabledFeatures);
if (mLineRasterizationFeatures.bresenhamLines)
{
enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
vk::AddToPNextChain(&createInfo, &mLineRasterizationFeatures);
}
else
if (mProvokingVertexFeatures.provokingVertexLast)
{
// Enable all available features
createInfo.pEnabledFeatures = &enabledFeatures.features;
enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
vk::AddToPNextChain(&createInfo, &mProvokingVertexFeatures);
}
if (vkGetPhysicalDeviceProperties2KHR)
if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
{
VkPhysicalDeviceProperties2 deviceProperties = {};
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
vk::AppendToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
vk::AddToPNextChain(&createInfo, &mVertexAttributeDivisorFeatures);
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
// We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
// exceeded
mMaxVertexAttribDivisor =
std::min(mVertexAttributeDivisorProperties.maxVertexAttribDivisor,
static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
}
bool supportsTransformFeedbackExt = getFeatures().supportsTransformFeedbackExtension.enabled;
if (supportsTransformFeedbackExt)
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
enabledDeviceExtensions.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
VkPhysicalDeviceTransformFeedbackFeaturesEXT xfbFeature = {};
xfbFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
xfbFeature.transformFeedback = true;
xfbFeature.geometryStreams = true;
vk::AppendToPNextChain(&enabledFeatures, &xfbFeature);
vk::AddToPNextChain(&createInfo, &mTransformFeedbackFeatures);
}
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.flags = 0;
createInfo.queueCreateInfoCount = 1;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(enabledDeviceLayerNames.size());
createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
createInfo.ppEnabledExtensionNames =
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
// Enable core features without assuming VkPhysicalDeviceFeatures2KHR is accepted in the pNext
// chain of VkDeviceCreateInfo.
createInfo.pEnabledFeatures = &enabledFeatures.features;
ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
volkLoadDevice(mDevice);
......@@ -1437,9 +1464,8 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
(&mFeatures), supportsShaderStencilExport,
ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsTransformFeedbackExtension,
ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION((&mFeatures), supportsTransformFeedbackExtension,
mTransformFeedbackFeatures.transformFeedback == VK_TRUE);
ANGLE_FEATURE_CONDITION((&mFeatures), emulateTransformFeedback,
(mFeatures.supportsTransformFeedbackExtension.enabled == VK_FALSE &&
......
......@@ -220,6 +220,8 @@ class RendererVk : angle::NonCopyable
angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
void ensureCapsInitialized() const;
void queryDeviceExtensionFeatures(const ExtensionNameList &deviceExtensionNames);
void initFeatures(const ExtensionNameList &extensions);
void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display,
......@@ -252,10 +254,13 @@ class RendererVk : angle::NonCopyable
VkDebugReportCallbackEXT mDebugReportCallback;
VkPhysicalDevice mPhysicalDevice;
VkPhysicalDeviceProperties mPhysicalDeviceProperties;
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
std::mutex mQueueMutex;
VkQueue mQueue;
......
......@@ -103,16 +103,15 @@ namespace vk
{
struct Format;
// Append ptr to end of pNext chain beginning at chainStart
// Prepend ptr to the pNext chain at chainStart
template <typename VulkanStruct1, typename VulkanStruct2>
void AppendToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr)
void AddToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr)
{
ASSERT(ptr->pNext == nullptr);
VkBaseOutStructure *localPtr = reinterpret_cast<VkBaseOutStructure *>(chainStart);
while (localPtr->pNext)
{
localPtr = localPtr->pNext;
}
localPtr->pNext = reinterpret_cast<VkBaseOutStructure *>(ptr);
ptr->pNext = localPtr->pNext;
localPtr->pNext = reinterpret_cast<VkBaseOutStructure *>(ptr);
}
extern const char *gLoaderLayersPathEnv;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment