diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk_unittests.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk_unittests.cc index 52ea64617b5..3de93ec63e5 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk_unittests.cc @@ -345,13 +345,13 @@ TEST(ContextVKTest, BatchSubmitCommandBuffersOnNonArm) { EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer())); EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer())); - // If command buffers are batch not submitted, we should have created them and - // a corresponding fence immediately. + // If command buffers are batched and not submitted, we should have created + // them and a corresponding fence immediately. auto functions = GetMockVulkanFunctions(context->GetDevice()); EXPECT_TRUE(std::find(functions->begin(), functions->end(), "vkAllocateCommandBuffers") != functions->end()); - EXPECT_TRUE(std::find(functions->begin(), functions->end(), - "vkCreateFence") != functions->end()); + EXPECT_FALSE(std::find(functions->begin(), functions->end(), + "vkCreateFence") != functions->end()); } TEST(ContextVKTest, AHBSwapchainCapabilitiesCanBeMissing) { diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.cc index 3f3e88d67d4..5e2a6d5dcac 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.cc @@ -119,6 +119,17 @@ AdrenoGPU GetAdrenoVersion(std::string_view version) { return result->second; } +PowerVRGPU GetPowerVRVersion(std::string_view version) { + // We don't really care about the specific model, just the series. + if (version.find("DXT") != std::string::npos) { + return PowerVRGPU::kDXT; + } + if (version.find("CXT") != std::string::npos) { + return PowerVRGPU::kCXT; + } + return PowerVRGPU::kUnknown; +} + MaliGPU GetMaliVersion(std::string_view version) { // These names are usually Mali-VERSION or Mali-Version-EXTRA_CRAP. auto dash_pos = version.find("Mali-"); @@ -264,6 +275,9 @@ DriverInfoVK::DriverInfoVK(const vk::PhysicalDevice& device) { case VendorVK::kARM: mali_gpu_ = GetMaliVersion(driver_name_); break; + case VendorVK::kPowerVR: + powervr_gpu_ = GetPowerVRVersion(driver_name_); + break; default: break; } @@ -356,7 +370,7 @@ bool DriverInfoVK::IsKnownBadDriver() const { // https://github.com/flutter/flutter/issues/160866 // https://github.com/flutter/flutter/issues/160804 // https://github.com/flutter/flutter/issues/160406 - if (vendor_ == VendorVK::kImgTec) { + if (powervr_gpu_.has_value() && powervr_gpu_.value() < PowerVRGPU::kCXT) { return true; } return false; @@ -370,4 +384,8 @@ std::optional DriverInfoVK::GetAdrenoGPUInfo() const { return adreno_gpu_; } +std::optional DriverInfoVK::GetPowerVRGPUInfo() const { + return powervr_gpu_; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.h index 3fd165df799..e40acae4d8c 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk.h @@ -108,6 +108,26 @@ enum class MaliGPU { kUnknown, }; +// Ordered by approximate release date. We currently don't attempt to +// parse the exact power VR GPU variant so newer names will fall back +// to OpenGL. This is acceptable for now. +enum class PowerVRGPU { + kUnknown, + // Not good. + kRogue, + // Vulkan may work, but not tested. + kAXE, + kAXM, + kAXT, + kBXE, + kBXM, + kBXS, + kBXT, + // First good vulkan drivers. + kCXT, + kDXT, +}; + enum class VendorVK { kUnknown, //---------------------------------------------------------------------------- @@ -251,6 +271,12 @@ class DriverInfoVK { /// std::optional GetAdrenoGPUInfo() const; + //---------------------------------------------------------------------------- + /// @brief Returns PowerVR GPU info if this is a PowerVR GPU, otherwise + /// std::nullopt. + /// + std::optional GetPowerVRGPUInfo() const; + private: bool is_valid_ = false; Version api_version_; @@ -260,6 +286,7 @@ class DriverInfoVK { // identified Adreno GPU. std::optional adreno_gpu_ = std::nullopt; std::optional mali_gpu_ = std::nullopt; + std::optional powervr_gpu_ = std::nullopt; std::string driver_name_; }; diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc index d2d12bd2bd0..a4db67885fd 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc @@ -7,6 +7,7 @@ #include "impeller/renderer/backend/vulkan/driver_info_vk.h" #include "impeller/renderer/backend/vulkan/surface_context_vk.h" #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h" +#include "impeller/renderer/backend/vulkan/workarounds_vk.h" namespace impeller::testing { @@ -250,15 +251,40 @@ TEST(DriverInfoVKTest, DisableOldXclipseDriver) { EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver()); } -TEST(DriverInfoVKTest, AllPowerVRDisabled) { - auto const context = +TEST(DriverInfoVKTest, OldPowerVRDisabled) { + std::shared_ptr context = MockVulkanContextBuilder() .SetPhysicalPropertiesCallback( [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) { prop->vendorID = 0x1010; prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + std::string name = "PowerVR Rogue GE8320"; + name.copy(prop->deviceName, name.size()); }) .Build(); + + EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver()); + EXPECT_EQ(context->GetDriverInfo()->GetPowerVRGPUInfo(), + std::optional(PowerVRGPU::kUnknown)); +} + +TEST(DriverInfoVKTest, NewPowerVREnabled) { + std::shared_ptr context = + MockVulkanContextBuilder() + .SetPhysicalPropertiesCallback( + [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) { + prop->vendorID = 0x1010; + prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + std::string name = "PowerVR DXT 123"; + name.copy(prop->deviceName, name.size()); + }) + .Build(); + + EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver()); + EXPECT_EQ(context->GetDriverInfo()->GetPowerVRGPUInfo(), + std::optional(PowerVRGPU::kDXT)); + EXPECT_TRUE(GetWorkaroundsFromDriverInfo(*context->GetDriverInfo()) + .input_attachment_self_dependency_broken); } } // namespace impeller::testing diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc index b511e34ce72..a2908707e31 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc @@ -11,22 +11,18 @@ WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info) { WorkaroundsVK workarounds; const auto& adreno_gpu = driver_info.GetAdrenoGPUInfo(); - const auto& mali_gpu = driver_info.GetMaliGPUInfo(); + const auto& powervr_gpu = driver_info.GetPowerVRGPUInfo(); - workarounds.batch_submit_command_buffer_timeout = true; if (adreno_gpu.has_value()) { workarounds.slow_primitive_restart_performance = true; workarounds.broken_mipmap_generation = true; if (adreno_gpu.value() <= AdrenoGPU::kAdreno630) { workarounds.input_attachment_self_dependency_broken = true; + workarounds.batch_submit_command_buffer_timeout = true; } - - if (adreno_gpu.value() >= AdrenoGPU::kAdreno702) { - workarounds.batch_submit_command_buffer_timeout = false; - } - } else if (mali_gpu.has_value()) { - workarounds.batch_submit_command_buffer_timeout = false; + } else if (powervr_gpu.has_value()) { + workarounds.input_attachment_self_dependency_broken = true; } return workarounds; } diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h index 8bb450454e4..4c35cbae899 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h @@ -25,6 +25,8 @@ struct WorkaroundsVK { /// On older 600 Series Adreno the input attachment / self dependency /// cycle for programmable blending is broken. + /// + /// Also broken on newer PowerVR. bool input_attachment_self_dependency_broken = false; /// Almost all Adreno series GPU (from 600 up to 800) have problems