Cleanup vulkan capabilities check and add multiview check

This commit is contained in:
Bastiaan Olij 2021-05-04 15:30:21 +10:00
parent 758bccf364
commit 90ef5d73c4
4 changed files with 93 additions and 17 deletions

View file

@ -7844,6 +7844,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
device_capabilities.subgroup_size = subgroup_capabilities.size;
device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd();
device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd();
// get info about further features
VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities();
device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1;
}
context = p_context;

View file

@ -352,8 +352,6 @@ Error VulkanContext::_initialize_extensions() {
return OK;
}
typedef void(VKAPI_PTR *_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice, VkPhysicalDeviceProperties2 *);
uint32_t VulkanContext::SubgroupCapabilities::supported_stages_flags_rd() const {
uint32_t flags = 0;
@ -496,20 +494,70 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const {
}
Error VulkanContext::_check_capabilities() {
// check subgroups
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
// for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android.
_vkGetPhysicalDeviceProperties2 func = (_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2");
if (func != nullptr) {
// so we check if the functions are accessible by getting their function pointers and skipping if not
// (note that the desktop loader does a better job here but the android loader doesn't)
// assume not supported until proven otherwise
multiview_capabilities.is_supported = false;
multiview_capabilities.max_view_count = 0;
multiview_capabilities.max_instance_count = 0;
subgroup_capabilities.size = 0;
subgroup_capabilities.supportedStages = 0;
subgroup_capabilities.supportedOperations = 0;
subgroup_capabilities.quadOperationsInAllStages = false;
// check for extended features
PFN_vkGetPhysicalDeviceFeatures2 device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2");
if (device_features_func == nullptr) {
// In Vulkan 1.0 might be accessible under its original extension name
device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
}
if (device_features_func != nullptr) {
// check our extended features
VkPhysicalDeviceMultiviewFeatures multiview_features;
multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
multiview_features.pNext = NULL;
VkPhysicalDeviceFeatures2 device_features;
device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
device_features.pNext = &multiview_features;
device_features_func(gpu, &device_features);
multiview_capabilities.is_supported = multiview_features.multiview;
// For now we ignore if multiview is available in geometry and tesselation as we do not currently support those
}
// check extended properties
PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2");
if (device_properties_func == nullptr) {
// In Vulkan 1.0 might be accessible under its original extension name
device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
}
if (device_properties_func != nullptr) {
VkPhysicalDeviceMultiviewProperties multiviewProperties;
VkPhysicalDeviceSubgroupProperties subgroupProperties;
VkPhysicalDeviceProperties2 physicalDeviceProperties;
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
subgroupProperties.pNext = nullptr;
VkPhysicalDeviceProperties2 physicalDeviceProperties;
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physicalDeviceProperties.pNext = &subgroupProperties;
func(gpu, &physicalDeviceProperties);
if (multiview_capabilities.is_supported) {
multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
multiviewProperties.pNext = &subgroupProperties;
physicalDeviceProperties.pNext = &multiviewProperties;
} else {
physicalDeviceProperties.pNext = &subgroupProperties;
}
device_properties_func(gpu, &physicalDeviceProperties);
subgroup_capabilities.size = subgroupProperties.subgroupSize;
subgroup_capabilities.supportedStages = subgroupProperties.supportedStages;
@ -519,18 +567,30 @@ Error VulkanContext::_check_capabilities() {
// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
// only output this when debugging?
print_line("- Vulkan subgroup size " + itos(subgroup_capabilities.size));
print_line("- Vulkan subgroup stages " + subgroup_capabilities.supported_stages_desc());
print_line("- Vulkan subgroup supported ops " + subgroup_capabilities.supported_operations_desc());
if (multiview_capabilities.is_supported) {
multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount;
multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex;
#ifdef DEBUG_ENABLED
print_line("- Vulkan multiview supported:");
print_line(" max views: " + itos(multiview_capabilities.max_view_count));
print_line(" max instances: " + itos(multiview_capabilities.max_instance_count));
} else {
print_line("- Vulkan multiview not supported");
#endif
}
#ifdef DEBUG_ENABLED
print_line("- Vulkan subgroup:");
print_line(" size: " + itos(subgroup_capabilities.size));
print_line(" stages: " + subgroup_capabilities.supported_stages_desc());
print_line(" supported ops: " + subgroup_capabilities.supported_operations_desc());
if (subgroup_capabilities.quadOperationsInAllStages) {
print_line("- Vulkan subgroup quad operations in all stages");
print_line(" quad operations in all stages");
}
} else {
subgroup_capabilities.size = 0;
subgroup_capabilities.supportedStages = 0;
subgroup_capabilities.supportedOperations = 0;
subgroup_capabilities.quadOperationsInAllStages = false;
print_line("- Couldn't call vkGetPhysicalDeviceProperties2");
#endif
}
return OK;

View file

@ -54,6 +54,12 @@ public:
String supported_operations_desc() const;
};
struct MultiviewCapabilities {
bool is_supported;
int32_t max_view_count;
int32_t max_instance_count;
};
private:
enum {
MAX_EXTENSIONS = 128,
@ -75,6 +81,7 @@ private:
uint32_t vulkan_major = 1;
uint32_t vulkan_minor = 0;
SubgroupCapabilities subgroup_capabilities;
MultiviewCapabilities multiview_capabilities;
String device_vendor;
String device_name;
@ -227,6 +234,7 @@ public:
uint32_t get_vulkan_major() const { return vulkan_major; };
uint32_t get_vulkan_minor() const { return vulkan_minor; };
SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; };
MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; };
VkDevice get_device();
VkPhysicalDevice get_physical_device();

View file

@ -93,10 +93,14 @@ public:
DeviceFamily device_family = DEVICE_UNKNOWN;
uint32_t version_major = 1.0;
uint32_t version_minor = 0.0;
// subgroup capabilities
uint32_t subgroup_size = 0;
uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations
// features
bool supports_multiview = false; // If true this device supports multiview options
};
typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);