зеркало из https://github.com/AvaloniaUI/angle.git
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>
This commit is contained in:
Родитель
3b2780e621
Коммит
13205b935d
|
@ -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))
|
||||
// Setup device initialization struct
|
||||
VkDeviceCreateInfo createInfo = {};
|
||||
|
||||
// Based on available extension features, decide on which extensions and features to enable.
|
||||
|
||||
if (mLineRasterizationFeatures.bresenhamLines)
|
||||
{
|
||||
enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
|
||||
vk::AddToPNextChain(&createInfo, &mLineRasterizationFeatures);
|
||||
}
|
||||
|
||||
if (mProvokingVertexFeatures.provokingVertexLast)
|
||||
{
|
||||
enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
vk::AddToPNextChain(&createInfo, &mProvokingVertexFeatures);
|
||||
}
|
||||
|
||||
if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
|
||||
{
|
||||
enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
|
||||
divisorFeatures.vertexAttributeInstanceRateDivisor = true;
|
||||
vk::AppendToPNextChain(&enabledFeatures, &divisorFeatures);
|
||||
vk::AddToPNextChain(&createInfo, &mVertexAttributeDivisorFeatures);
|
||||
|
||||
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT divisorProperties = {};
|
||||
divisorProperties.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
|
||||
|
||||
VkPhysicalDeviceProperties2 deviceProperties = {};
|
||||
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
vk::AppendToPNextChain(&deviceProperties, &divisorProperties);
|
||||
|
||||
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
|
||||
// We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
|
||||
// exceeded
|
||||
mMaxVertexAttribDivisor =
|
||||
std::min(divisorProperties.maxVertexAttribDivisor,
|
||||
std::min(mVertexAttributeDivisorProperties.maxVertexAttribDivisor,
|
||||
static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
|
||||
vk::AppendToPNextChain(&createInfo, &enabledFeatures);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable all available features
|
||||
createInfo.pEnabledFeatures = &enabledFeatures.features;
|
||||
}
|
||||
|
||||
if (vkGetPhysicalDeviceProperties2KHR)
|
||||
{
|
||||
VkPhysicalDeviceProperties2 deviceProperties = {};
|
||||
deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
vk::AppendToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
|
||||
|
||||
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче