Implement support for VkPhysicalDeviceFeatures2

This commit is contained in:
Scott Mansell 2023-01-17 01:30:22 +13:00 committed by nyanpasu64
parent 234d825f0d
commit ada63c9e08
3 changed files with 95 additions and 25 deletions

View File

@ -22,6 +22,26 @@ static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validatio
std::unique_ptr<VulkanContext> g_vulkan_context;
void DolphinFeatures::PopulateNextChain(uint64_t device_api_version,
std::vector<std::string>& enabled_extentions)
{
// While the vulkan spec does require implementations to ignore entries in the pNext chain that
// don't know about, it also requires clients to only attach structures that they have enabled.
// So, we have to selectively build the pNext chain.
sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
// NOTE: This does introduce a limitation that we can't enable 1.1 features unless the device
// supports 1.2. We could support the old method, but I'm not sure it's worth the effort
AppendIf(&features11, device_api_version >= VK_API_VERSION_1_2);
AppendIf(&features12, device_api_version >= VK_API_VERSION_1_2);
auto have_extension = [&enabled_extentions](const char* name) {
return std::find(enabled_extentions.begin(), enabled_extentions.end(), name) !=
enabled_extentions.end();
};
}
VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_device)
: m_instance(instance), m_physical_device(physical_device)
{
@ -599,35 +619,49 @@ bool VulkanContext::SelectDeviceFeatures()
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(m_physical_device, &properties);
VkPhysicalDeviceFeatures available_features;
vkGetPhysicalDeviceFeatures(m_physical_device, &available_features);
DolphinFeatures available = {};
// To use vkGetPhysicalDeviceFeatures2, we need to make sure the device api version is at
// least 1.1
if (!vkGetPhysicalDeviceFeatures2 || properties.apiVersion == VK_API_VERSION_1_0)
{
// But we can fallback to the old vkGetPhysicalDeviceFeatures.
vkGetPhysicalDeviceFeatures(m_physical_device, &available.features);
}
else
{
available.PopulateNextChain(properties.apiVersion, m_device_extensions);
m_device_features.PopulateNextChain(properties.apiVersion, m_device_extensions);
vkGetPhysicalDeviceFeatures2(m_physical_device, &available);
}
// Not having geometry shaders or wide lines will cause issues with rendering.
if (!available_features.geometryShader && !available_features.wideLines)
if (!available.features.geometryShader && !available.features.wideLines)
WARN_LOG_FMT(VIDEO, "Vulkan: Missing both geometryShader and wideLines features.");
if (!available_features.largePoints)
if (!available.features.largePoints)
WARN_LOG_FMT(VIDEO, "Vulkan: Missing large points feature. CPU EFB writes will be slower.");
if (!available_features.occlusionQueryPrecise)
if (!available.features.occlusionQueryPrecise)
{
WARN_LOG_FMT(VIDEO,
"Vulkan: Missing precise occlusion queries. Perf queries will be inaccurate.");
}
// Enable the features we use.
m_device_features.dualSrcBlend = available_features.dualSrcBlend;
m_device_features.geometryShader = available_features.geometryShader;
m_device_features.samplerAnisotropy = available_features.samplerAnisotropy;
m_device_features.logicOp = available_features.logicOp;
m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
m_device_features.sampleRateShading = available_features.sampleRateShading;
m_device_features.largePoints = available_features.largePoints;
m_device_features.shaderStorageImageMultisample =
available_features.shaderStorageImageMultisample;
m_device_features.shaderTessellationAndGeometryPointSize =
available_features.shaderTessellationAndGeometryPointSize;
m_device_features.occlusionQueryPrecise = available_features.occlusionQueryPrecise;
m_device_features.shaderClipDistance = available_features.shaderClipDistance;
m_device_features.depthClamp = available_features.depthClamp;
m_device_features.textureCompressionBC = available_features.textureCompressionBC;
m_device_features.features.dualSrcBlend = available.features.dualSrcBlend;
m_device_features.features.geometryShader = available.features.geometryShader;
m_device_features.features.samplerAnisotropy = available.features.samplerAnisotropy;
m_device_features.features.logicOp = available.features.logicOp;
m_device_features.features.fragmentStoresAndAtomics = available.features.fragmentStoresAndAtomics;
m_device_features.features.sampleRateShading = available.features.sampleRateShading;
m_device_features.features.largePoints = available.features.largePoints;
m_device_features.features.shaderStorageImageMultisample =
available.features.shaderStorageImageMultisample;
m_device_features.features.shaderTessellationAndGeometryPointSize =
available.features.shaderTessellationAndGeometryPointSize;
m_device_features.features.occlusionQueryPrecise = available.features.occlusionQueryPrecise;
m_device_features.features.shaderClipDistance = available.features.shaderClipDistance;
m_device_features.features.depthClamp = available.features.depthClamp;
m_device_features.features.textureCompressionBC = available.features.textureCompressionBC;
return true;
}
@ -748,7 +782,15 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
if (!SelectDeviceFeatures())
return false;
device_info.pEnabledFeatures = &m_device_features;
if (m_device_properties.apiVersion < VK_API_VERSION_1_1)
{
device_info.pEnabledFeatures = &m_device_features.features;
}
else
{
device_info.pEnabledFeatures = nullptr;
device_info.pNext = &m_device_features;
}
// Enable debug layer on debug builds
if (enable_validation_layer)

View File

@ -15,6 +15,33 @@
namespace Vulkan
{
// Small wrapper to make it easier to deal with VkPhysicalDeviceFeatures2 and it's pNext chain
struct DolphinFeatures : public VkPhysicalDeviceFeatures2
{
VkPhysicalDeviceVulkan12Features features12 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};
VkPhysicalDeviceVulkan11Features features11 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES};
DolphinFeatures() : VkPhysicalDeviceFeatures2(), m_tail(&pNext) {}
void PopulateNextChain(uint64_t device_api_version, std::vector<std::string>& enabled_extentions);
private:
void** m_tail;
template <typename T>
void AppendIf(T* feature, bool cond)
{
if (cond)
{
*m_tail = feature;
m_tail = &feature->pNext;
}
}
};
class VulkanContext
{
public:
@ -70,16 +97,16 @@ public:
return m_device_memory_properties;
}
const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_properties; }
const VkPhysicalDeviceFeatures& GetDeviceFeatures() const { return m_device_features; }
const VkPhysicalDeviceFeatures& GetDeviceFeatures() const { return m_device_features.features; }
const VkPhysicalDeviceLimits& GetDeviceLimits() const { return m_device_properties.limits; }
// Support bits
bool SupportsAnisotropicFiltering() const
{
return m_device_features.samplerAnisotropy == VK_TRUE;
return m_device_features.features.samplerAnisotropy == VK_TRUE;
}
bool SupportsPreciseOcclusionQueries() const
{
return m_device_features.occlusionQueryPrecise == VK_TRUE;
return m_device_features.features.occlusionQueryPrecise == VK_TRUE;
}
u32 GetShaderSubgroupSize() const { return m_shader_subgroup_size; }
bool SupportsShaderSubgroupOperations() const { return m_supports_shader_subgroup_operations; }
@ -138,7 +165,7 @@ private:
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
VkPhysicalDeviceFeatures m_device_features = {};
DolphinFeatures m_device_features = {};
VkPhysicalDeviceProperties m_device_properties = {};
VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};

View File

@ -23,6 +23,7 @@ VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceVersion, false)
VULKAN_INSTANCE_ENTRY_POINT(vkDestroyInstance, true)
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures2, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFormatProperties, true)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceImageFormatProperties, true)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceProperties, true)