Implement support for VkPhysicalDeviceFeatures2
This commit is contained in:
parent
234d825f0d
commit
ada63c9e08
|
@ -22,6 +22,26 @@ static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validatio
|
||||||
|
|
||||||
std::unique_ptr<VulkanContext> g_vulkan_context;
|
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)
|
VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_device)
|
||||||
: m_instance(instance), m_physical_device(physical_device)
|
: m_instance(instance), m_physical_device(physical_device)
|
||||||
{
|
{
|
||||||
|
@ -599,35 +619,49 @@ bool VulkanContext::SelectDeviceFeatures()
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
vkGetPhysicalDeviceProperties(m_physical_device, &properties);
|
vkGetPhysicalDeviceProperties(m_physical_device, &properties);
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures available_features;
|
DolphinFeatures available = {};
|
||||||
vkGetPhysicalDeviceFeatures(m_physical_device, &available_features);
|
|
||||||
|
// 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.
|
// 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.");
|
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.");
|
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,
|
WARN_LOG_FMT(VIDEO,
|
||||||
"Vulkan: Missing precise occlusion queries. Perf queries will be inaccurate.");
|
"Vulkan: Missing precise occlusion queries. Perf queries will be inaccurate.");
|
||||||
}
|
}
|
||||||
// Enable the features we use.
|
// Enable the features we use.
|
||||||
m_device_features.dualSrcBlend = available_features.dualSrcBlend;
|
m_device_features.features.dualSrcBlend = available.features.dualSrcBlend;
|
||||||
m_device_features.geometryShader = available_features.geometryShader;
|
m_device_features.features.geometryShader = available.features.geometryShader;
|
||||||
m_device_features.samplerAnisotropy = available_features.samplerAnisotropy;
|
m_device_features.features.samplerAnisotropy = available.features.samplerAnisotropy;
|
||||||
m_device_features.logicOp = available_features.logicOp;
|
m_device_features.features.logicOp = available.features.logicOp;
|
||||||
m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
|
m_device_features.features.fragmentStoresAndAtomics = available.features.fragmentStoresAndAtomics;
|
||||||
m_device_features.sampleRateShading = available_features.sampleRateShading;
|
m_device_features.features.sampleRateShading = available.features.sampleRateShading;
|
||||||
m_device_features.largePoints = available_features.largePoints;
|
m_device_features.features.largePoints = available.features.largePoints;
|
||||||
m_device_features.shaderStorageImageMultisample =
|
m_device_features.features.shaderStorageImageMultisample =
|
||||||
available_features.shaderStorageImageMultisample;
|
available.features.shaderStorageImageMultisample;
|
||||||
m_device_features.shaderTessellationAndGeometryPointSize =
|
m_device_features.features.shaderTessellationAndGeometryPointSize =
|
||||||
available_features.shaderTessellationAndGeometryPointSize;
|
available.features.shaderTessellationAndGeometryPointSize;
|
||||||
m_device_features.occlusionQueryPrecise = available_features.occlusionQueryPrecise;
|
m_device_features.features.occlusionQueryPrecise = available.features.occlusionQueryPrecise;
|
||||||
m_device_features.shaderClipDistance = available_features.shaderClipDistance;
|
m_device_features.features.shaderClipDistance = available.features.shaderClipDistance;
|
||||||
m_device_features.depthClamp = available_features.depthClamp;
|
m_device_features.features.depthClamp = available.features.depthClamp;
|
||||||
m_device_features.textureCompressionBC = available_features.textureCompressionBC;
|
m_device_features.features.textureCompressionBC = available.features.textureCompressionBC;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,7 +782,15 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
|
||||||
if (!SelectDeviceFeatures())
|
if (!SelectDeviceFeatures())
|
||||||
return false;
|
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
|
// Enable debug layer on debug builds
|
||||||
if (enable_validation_layer)
|
if (enable_validation_layer)
|
||||||
|
|
|
@ -15,6 +15,33 @@
|
||||||
|
|
||||||
namespace Vulkan
|
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
|
class VulkanContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -70,16 +97,16 @@ public:
|
||||||
return m_device_memory_properties;
|
return m_device_memory_properties;
|
||||||
}
|
}
|
||||||
const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_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; }
|
const VkPhysicalDeviceLimits& GetDeviceLimits() const { return m_device_properties.limits; }
|
||||||
// Support bits
|
// Support bits
|
||||||
bool SupportsAnisotropicFiltering() const
|
bool SupportsAnisotropicFiltering() const
|
||||||
{
|
{
|
||||||
return m_device_features.samplerAnisotropy == VK_TRUE;
|
return m_device_features.features.samplerAnisotropy == VK_TRUE;
|
||||||
}
|
}
|
||||||
bool SupportsPreciseOcclusionQueries() const
|
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; }
|
u32 GetShaderSubgroupSize() const { return m_shader_subgroup_size; }
|
||||||
bool SupportsShaderSubgroupOperations() const { return m_supports_shader_subgroup_operations; }
|
bool SupportsShaderSubgroupOperations() const { return m_supports_shader_subgroup_operations; }
|
||||||
|
@ -138,7 +165,7 @@ private:
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
|
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures m_device_features = {};
|
DolphinFeatures m_device_features = {};
|
||||||
VkPhysicalDeviceProperties m_device_properties = {};
|
VkPhysicalDeviceProperties m_device_properties = {};
|
||||||
VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};
|
VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ VULKAN_MODULE_ENTRY_POINT(vkEnumerateInstanceVersion, false)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkDestroyInstance, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkDestroyInstance, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkEnumeratePhysicalDevices, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures, true)
|
||||||
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures2, false)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFormatProperties, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFormatProperties, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceImageFormatProperties, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceImageFormatProperties, true)
|
||||||
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceProperties, true)
|
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceProperties, true)
|
||||||
|
|
Loading…
Reference in New Issue