diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc index 3fb53bcce4..ad5a2db41c 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -627,7 +627,7 @@ bool CapabilitiesVK::SupportsTextureToTextureBlits() const { // |Capabilities| bool CapabilitiesVK::SupportsFramebufferFetch() const { - return true; + return has_framebuffer_fetch_; } // |Capabilities| @@ -762,6 +762,7 @@ ISize CapabilitiesVK::GetMaximumRenderPassAttachmentSize() const { void CapabilitiesVK::ApplyWorkarounds(const WorkaroundsVK& workarounds) { has_primitive_restart_ = !workarounds.slow_primitive_restart_performance; + has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken; } } // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.h index 3a7824e22c..c52194f038 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -304,6 +304,7 @@ class CapabilitiesVK final : public Capabilities, ISize max_render_pass_attachment_size_ = ISize{0, 0}; bool has_triangle_fans_ = true; bool has_primitive_restart_ = true; + bool has_framebuffer_fetch_ = true; bool is_valid_ = false; // The embedder.h API is responsible for providing the instance and device 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 51d98b1bea..5b52a0da1d 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 @@ -194,4 +194,33 @@ TEST(DriverInfoVKTest, EnabledDevicesAdreno) { EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 702")); } +bool CanUseFramebufferFetch(std::string_view driver_name, bool qc = true) { + auto const context = + MockVulkanContextBuilder() + .SetPhysicalPropertiesCallback( + [&driver_name, qc](VkPhysicalDevice device, + VkPhysicalDeviceProperties* prop) { + if (qc) { + prop->vendorID = 0x168C; // Qualcomm + } else { + prop->vendorID = 0x13B5; // ARM + } + driver_name.copy(prop->deviceName, driver_name.size()); + prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + }) + .Build(); + return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo()) + .input_attachment_self_dependency_broken; +} + +TEST(DriverInfoVKTest, CanUseFramebufferFetch) { + // Adreno no primitive restart on models as or older than 630. + EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 540", true)); + EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 630", true)); + + EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 640", true)); + EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 750", true)); + EXPECT_TRUE(CanUseFramebufferFetch("Mali-G51", false)); +} + } // 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 f0d1b0586c..b511e34ce7 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/renderer/backend/vulkan/workarounds_vk.h" +#include "impeller/renderer/backend/vulkan/driver_info_vk.h" namespace impeller { @@ -17,6 +18,10 @@ WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info) { workarounds.slow_primitive_restart_performance = true; workarounds.broken_mipmap_generation = true; + if (adreno_gpu.value() <= AdrenoGPU::kAdreno630) { + workarounds.input_attachment_self_dependency_broken = true; + } + if (adreno_gpu.value() >= AdrenoGPU::kAdreno702) { workarounds.batch_submit_command_buffer_timeout = false; } 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 b2b70bc61d..8bb450454e 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h @@ -23,6 +23,10 @@ struct WorkaroundsVK { /// be logically combined. bool batch_submit_command_buffer_timeout = false; + /// On older 600 Series Adreno the input attachment / self dependency + /// cycle for programmable blending is broken. + bool input_attachment_self_dependency_broken = false; + /// Almost all Adreno series GPU (from 600 up to 800) have problems /// generating mipmaps, resulting in corruption of the mip levels. /// See: