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;
|
||||
|
||||
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)
|
||||
|
|
|
@ -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 = {};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue