summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-12-26 01:50:25 -0300
committerGravatar ReinUsesLisp2020-12-31 02:07:33 -0300
commitf687392e6f29d1b65cd80a18f86a55122bde417c (patch)
treeaca4dd89e0e67d7055bb844cf9ceaf2e8c6c8cf2 /src
parentrenderer_vulkan: Remove two step initialization on VKDevice (diff)
downloadyuzu-f687392e6f29d1b65cd80a18f86a55122bde417c.tar.gz
yuzu-f687392e6f29d1b65cd80a18f86a55122bde417c.tar.xz
yuzu-f687392e6f29d1b65cd80a18f86a55122bde417c.zip
vk_device: Stop initialization when device is not suitable
VKDevice::IsSuitable was not being called. To address this issue, check suitability before initialization and throw an exception if it fails. By doing this, we can deduplicate some code on queue searches. Previosuly we would first search if a present and graphics queue existed, then on initialization we would search again to find the index.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp96
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h4
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
551bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) { 552void 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
641std::vector<const char*> VKDevice::LoadExtensions() { 613std::vector<const char*> VKDevice::LoadExtensions() {
@@ -794,28 +766,34 @@ std::vector<const char*> VKDevice::LoadExtensions() {
794} 766}
795 767
796void VKDevice::SetupFamilies(VkSurfaceKHR surface) { 768void 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
821void VKDevice::SetupFeatures() { 799void 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
232private:
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
235private:
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