diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_device.cpp | 96 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_device.h | 4 |
2 files changed, 39 insertions, 61 deletions
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index 831603e87..07edf556d 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -210,6 +210,7 @@ VKDevice::VKDevice(VkInstance instance_, u32 instance_version_, vk::PhysicalDevi | |||
| 210 | VkSurfaceKHR surface, const vk::InstanceDispatch& dld_) | 210 | VkSurfaceKHR surface, const vk::InstanceDispatch& dld_) |
| 211 | : instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()}, | 211 | : instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()}, |
| 212 | instance_version{instance_version_}, format_properties{GetFormatProperties(physical, dld)} { | 212 | instance_version{instance_version_}, format_properties{GetFormatProperties(physical, dld)} { |
| 213 | CheckSuitability(); | ||
| 213 | SetupFamilies(surface); | 214 | SetupFamilies(surface); |
| 214 | SetupFeatures(); | 215 | SetupFeatures(); |
| 215 | 216 | ||
| @@ -548,64 +549,41 @@ bool VKDevice::IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags wa | |||
| 548 | return (supported_usage & wanted_usage) == wanted_usage; | 549 | return (supported_usage & wanted_usage) == wanted_usage; |
| 549 | } | 550 | } |
| 550 | 551 | ||
| 551 | bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) { | 552 | void VKDevice::CheckSuitability() const { |
| 552 | bool is_suitable = true; | ||
| 553 | std::bitset<REQUIRED_EXTENSIONS.size()> available_extensions; | 553 | std::bitset<REQUIRED_EXTENSIONS.size()> available_extensions; |
| 554 | 554 | for (const VkExtensionProperties& property : physical.EnumerateDeviceExtensionProperties()) { | |
| 555 | for (const auto& prop : physical.EnumerateDeviceExtensionProperties()) { | ||
| 556 | for (std::size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { | 555 | for (std::size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { |
| 557 | if (available_extensions[i]) { | 556 | if (available_extensions[i]) { |
| 558 | continue; | 557 | continue; |
| 559 | } | 558 | } |
| 560 | const std::string_view name{prop.extensionName}; | 559 | const std::string_view name{property.extensionName}; |
| 561 | available_extensions[i] = name == REQUIRED_EXTENSIONS[i]; | 560 | available_extensions[i] = name == REQUIRED_EXTENSIONS[i]; |
| 562 | } | 561 | } |
| 563 | } | 562 | } |
| 564 | if (!available_extensions.all()) { | 563 | for (size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { |
| 565 | for (std::size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { | 564 | if (available_extensions[i]) { |
| 566 | if (available_extensions[i]) { | ||
| 567 | continue; | ||
| 568 | } | ||
| 569 | LOG_ERROR(Render_Vulkan, "Missing required extension: {}", REQUIRED_EXTENSIONS[i]); | ||
| 570 | is_suitable = false; | ||
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | bool has_graphics{}, has_present{}; | ||
| 575 | const std::vector queue_family_properties = physical.GetQueueFamilyProperties(); | ||
| 576 | for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) { | ||
| 577 | const auto& family = queue_family_properties[i]; | ||
| 578 | if (family.queueCount == 0) { | ||
| 579 | continue; | 565 | continue; |
| 580 | } | 566 | } |
| 581 | has_graphics |= family.queueFlags & VK_QUEUE_GRAPHICS_BIT; | 567 | LOG_ERROR(Render_Vulkan, "Missing required extension: {}", REQUIRED_EXTENSIONS[i]); |
| 582 | has_present |= physical.GetSurfaceSupportKHR(i, surface); | 568 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
| 583 | } | 569 | } |
| 584 | if (!has_graphics || !has_present) { | ||
| 585 | LOG_ERROR(Render_Vulkan, "Device lacks a graphics and present queue"); | ||
| 586 | is_suitable = false; | ||
| 587 | } | ||
| 588 | |||
| 589 | // TODO(Rodrigo): Check if the device matches all requeriments. | 570 | // TODO(Rodrigo): Check if the device matches all requeriments. |
| 590 | const auto properties{physical.GetProperties()}; | 571 | const VkPhysicalDeviceLimits& limits{properties.limits}; |
| 591 | const auto& limits{properties.limits}; | ||
| 592 | 572 | ||
| 593 | constexpr u32 required_ubo_size = 65536; | 573 | constexpr u32 required_ubo_size = 65536; |
| 594 | if (limits.maxUniformBufferRange < required_ubo_size) { | 574 | if (limits.maxUniformBufferRange < required_ubo_size) { |
| 595 | LOG_ERROR(Render_Vulkan, "Device UBO size {} is too small, {} is required", | 575 | LOG_ERROR(Render_Vulkan, "Device UBO size {} is too small, {} is required", |
| 596 | limits.maxUniformBufferRange, required_ubo_size); | 576 | limits.maxUniformBufferRange, required_ubo_size); |
| 597 | is_suitable = false; | 577 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 598 | } | 578 | } |
| 599 | |||
| 600 | constexpr u32 required_num_viewports = 16; | 579 | constexpr u32 required_num_viewports = 16; |
| 601 | if (limits.maxViewports < required_num_viewports) { | 580 | if (limits.maxViewports < required_num_viewports) { |
| 602 | LOG_INFO(Render_Vulkan, "Device number of viewports {} is too small, {} is required", | 581 | LOG_INFO(Render_Vulkan, "Device number of viewports {} is too small, {} is required", |
| 603 | limits.maxViewports, required_num_viewports); | 582 | limits.maxViewports, required_num_viewports); |
| 604 | is_suitable = false; | 583 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 605 | } | 584 | } |
| 606 | 585 | const VkPhysicalDeviceFeatures features{physical.GetFeatures()}; | |
| 607 | const auto features{physical.GetFeatures()}; | 586 | const std::array feature_report{ |
| 608 | const std::array feature_report = { | ||
| 609 | std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"), | 587 | std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"), |
| 610 | std::make_pair(features.imageCubeArray, "imageCubeArray"), | 588 | std::make_pair(features.imageCubeArray, "imageCubeArray"), |
| 611 | std::make_pair(features.independentBlend, "independentBlend"), | 589 | std::make_pair(features.independentBlend, "independentBlend"), |
| @@ -623,19 +601,13 @@ bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) { | |||
| 623 | std::make_pair(features.shaderStorageImageWriteWithoutFormat, | 601 | std::make_pair(features.shaderStorageImageWriteWithoutFormat, |
| 624 | "shaderStorageImageWriteWithoutFormat"), | 602 | "shaderStorageImageWriteWithoutFormat"), |
| 625 | }; | 603 | }; |
| 626 | for (const auto& [supported, name] : feature_report) { | 604 | for (const auto& [is_supported, name] : feature_report) { |
| 627 | if (supported) { | 605 | if (is_supported) { |
| 628 | continue; | 606 | continue; |
| 629 | } | 607 | } |
| 630 | LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name); | 608 | LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name); |
| 631 | is_suitable = false; | 609 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 632 | } | ||
| 633 | |||
| 634 | if (!is_suitable) { | ||
| 635 | LOG_ERROR(Render_Vulkan, "{} is not suitable", properties.deviceName); | ||
| 636 | } | 610 | } |
| 637 | |||
| 638 | return is_suitable; | ||
| 639 | } | 611 | } |
| 640 | 612 | ||
| 641 | std::vector<const char*> VKDevice::LoadExtensions() { | 613 | std::vector<const char*> VKDevice::LoadExtensions() { |
| @@ -794,28 +766,34 @@ std::vector<const char*> VKDevice::LoadExtensions() { | |||
| 794 | } | 766 | } |
| 795 | 767 | ||
| 796 | void VKDevice::SetupFamilies(VkSurfaceKHR surface) { | 768 | void VKDevice::SetupFamilies(VkSurfaceKHR surface) { |
| 797 | std::optional<u32> graphics_family_, present_family_; | ||
| 798 | |||
| 799 | const std::vector queue_family_properties = physical.GetQueueFamilyProperties(); | 769 | const std::vector queue_family_properties = physical.GetQueueFamilyProperties(); |
| 800 | for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) { | 770 | std::optional<u32> graphics; |
| 801 | if (graphics_family_ && present_family_) | 771 | std::optional<u32> present; |
| 772 | for (u32 index = 0; index < static_cast<u32>(queue_family_properties.size()); ++index) { | ||
| 773 | if (graphics && present) { | ||
| 802 | break; | 774 | break; |
| 803 | 775 | } | |
| 804 | const auto& queue_family = queue_family_properties[i]; | 776 | const VkQueueFamilyProperties& queue_family = queue_family_properties[index]; |
| 805 | if (queue_family.queueCount == 0) | 777 | if (queue_family.queueCount == 0) { |
| 806 | continue; | 778 | continue; |
| 807 | 779 | } | |
| 808 | if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { | 780 | if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { |
| 809 | graphics_family_ = i; | 781 | graphics = index; |
| 810 | } | 782 | } |
| 811 | if (physical.GetSurfaceSupportKHR(i, surface)) { | 783 | if (physical.GetSurfaceSupportKHR(index, surface)) { |
| 812 | present_family_ = i; | 784 | present = index; |
| 813 | } | 785 | } |
| 814 | } | 786 | } |
| 815 | ASSERT(graphics_family_ && present_family_); | 787 | if (!graphics) { |
| 816 | 788 | LOG_ERROR(Render_Vulkan, "Device lacks a graphics queue"); | |
| 817 | graphics_family = *graphics_family_; | 789 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 818 | present_family = *present_family_; | 790 | } |
| 791 | if (!present) { | ||
| 792 | LOG_ERROR(Render_Vulkan, "Device lacks a present queue"); | ||
| 793 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); | ||
| 794 | } | ||
| 795 | graphics_family = *graphics; | ||
| 796 | present_family = *present; | ||
| 819 | } | 797 | } |
| 820 | 798 | ||
| 821 | void VKDevice::SetupFeatures() { | 799 | void VKDevice::SetupFeatures() { |
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h index 67617f86d..63e123d02 100644 --- a/src/video_core/renderer_vulkan/vk_device.h +++ b/src/video_core/renderer_vulkan/vk_device.h | |||
| @@ -229,10 +229,10 @@ public: | |||
| 229 | return use_asynchronous_shaders; | 229 | return use_asynchronous_shaders; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | private: | ||
| 232 | /// Checks if the physical device is suitable. | 233 | /// Checks if the physical device is suitable. |
| 233 | static bool IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface); | 234 | void CheckSuitability() const; |
| 234 | 235 | ||
| 235 | private: | ||
| 236 | /// Loads extensions into a vector and stores available ones in this object. | 236 | /// Loads extensions into a vector and stores available ones in this object. |
| 237 | std::vector<const char*> LoadExtensions(); | 237 | std::vector<const char*> LoadExtensions(); |
| 238 | 238 | ||