Skip to content

[Impeller] Scope the broken mipmap workaround to the textures it affects - #190186

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
bdero:bdero/adreno-manual-mip-provenance
Sep 23, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:masterfrom
bdero:bdero/adreno-manual-mip-provenance

Conversation

@bdero

@bdero bdero commented Jul 29, 2026 •

Copy link
Copy Markdown
Member

Fixes bdero/flutter_scene#241. Related to #161283.

Adreno drivers corrupt blit-generated mip chains. The workaround for that rewrote every Vulkan sampler to MipFilter::kBase, so nothing in the process could be sampled past its base mip level. But the corruption belongs to the texture whose levels were generated, not to the sampler, so textures with hand-uploaded mip chains (prefiltered environment maps, for one) lost their mip filtering for no reason. Flutter GPU is hit hardest, since it exposes no mipmap generation at all and every mip chain it binds was uploaded by the app.

The workaround now lives with the texture. On affected drivers a mipped sampled texture also gets an image view covering only the base level, and TextureVK::GetSampledImageView hands that view out for textures those drivers mipped. Generated chains stay unreadable past the base level, every other texture samples as requested, and the sampler library, SamplerDescriptor, and lib/gpu no longer carry any of it.

A texture with mip_count > 1 whose levels were never written is no longer masked on these devices, which matches its behavior on every other platform. #190264 fixes the generation itself and will delete what is left here.

Pre-launch Checklist

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests flutter-gpu team-fluttergpu Owned by Flutter GPU team labels Jul 29, 2026
@github-project-automation github-project-automation Bot moved this to 🤔 Needs Triage in Flutter GPU Jul 29, 2026
@bdero
bdero marked this pull request as ready for review July 29, 2026 06:59

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an allow_manual_mip_sampling flag to SamplerDescriptor to prevent hand-uploaded mipmaps from being clamped to the base mip level by the Adreno workaround, and adds corresponding unit tests. Feedback suggests that using NeedsMipmapGeneration() to detect hand-uploaded mipmaps relies on an implementation detail, and recommends explicitly tracking manual mipmaps or adding a dedicated method to improve maintainability.

@bdero

bdero commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Working on an alternative to this approach at the moment. See comment: #189966 (comment)

@gaaclarke
gaaclarke marked this pull request as draft August 3, 2026 18:15
@gaaclarke

Copy link
Copy Markdown
Member

considering you mentioned you are still working on this, moved to draft

@bdero bdero changed the title [Impeller] Sample hand-uploaded mip chains on Adreno Vulkan [Impeller] Scope the broken mipmap workaround to the textures it affects Aug 6, 2026
@github-actions github-actions Bot removed flutter-gpu team-fluttergpu Owned by Flutter GPU team labels Aug 6, 2026
@bdero
bdero requested a review from gaaclarke August 6, 2026 04:22
@bdero
bdero marked this pull request as ready for review August 6, 2026 04:22
@bdero
bdero force-pushed the bdero/adreno-manual-mip-provenance branch from f8e4001 to c9c8bdc Compare August 6, 2026 04:23
@bdero bdero added the CICD Run CI/CD label Aug 6, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a workaround for Vulkan drivers that generate corrupt mipmap levels by creating and sampling through an image view restricted to the base mip level, replacing the previous sampler-level workaround. The review feedback identifies a potential resource leak in 'allocator_vk.cc' if the base mip image view creation fails and returns early, as well as a compilation error on 32-bit platforms in 'mock_vulkan.cc' due to casting a 64-bit atomic integer to a pointer type.

I am having trouble creating individual review comments. Click here to see my feedback.

engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc (472-478)

high

If device.createImageViewUnique fails, returning early here will leak the allocated VkImage and VmaAllocation because they have not yet been wrapped in the RAII UniqueImageVMA container (which only happens at line 481 inside ImageResource).\n\nSince the base mip image view is a workaround for sampling on specific drivers, a failure to create it should not fail the entire texture allocation. We can safely log the error and proceed without the base mip view, falling back to the main image view.

      auto [base_result, base_view] = device.createImageViewUnique(view_info);\n      if (base_result == vk::Result::eSuccess) {\n        base_mip_image_view = std::move(base_view);\n      } else {\n        VALIDATION_LOG << \"Unable to create a base mip image view: \"\n                       << vk::to_string(base_result);\n      }

engine/src/flutter/impeller/renderer/backend/vulkan/test/mock_vulkan.cc (488-489)

medium

On 32-bit platforms (such as 32-bit ARM, which Flutter still supports), VkImageView is a 32-bit pointer type. Casting a 64-bit integer (std::atomic_uint64_t) to a 32-bit pointer using reinterpret_cast will trigger a compilation error (-Wint-to-pointer-cast).\n\nUsing uintptr_t ensures that the integer is always the same size as a pointer on the target architecture, preventing compilation failures on 32-bit builds.

  static std::atomic<uintptr_t> next_handle = 0xFEE1DEAD;\n  *pView = reinterpret_cast<VkImageView>(next_handle.fetch_add(1));

@bdero

bdero commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

@gaaclarke I revisited this to make the workaround for this bug less far reaching, so that it doesn't unnecessarily touch mip chains that have nothing to do with automatic mip generation (and are thus not affected by the Adreno bug).

I think we should land this workaround scope reduction before considering something like #190264, since adding an alternative rendering path for automatic mips is a much more involved change (and we might be better off doing that once I have compute pipelines in a better place anyway).

@bdero

bdero commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a workaround for Vulkan drivers that generate corrupt mipmap levels by creating and sampling from an image view restricted to the base mip level. Feedback on these changes highlights a potential resource leak in allocator_vk.cc if the base mip image view creation fails and returns early, suggesting instead to degrade gracefully. Additionally, it is recommended to move the new texture_vk_unittests.cc file into the test/ subdirectory to maintain consistency with the project's directory structure.

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some clang-tidy failures:

❌ Failures for clang-tidy on /b/s/w/ir/cache/builder/engine/src/flutter/impeller/renderer/backend/vulkan/texture_vk_unittests.cc:
../../../flutter/impeller/renderer/backend/vulkan/test/mock_vulkan.h:114:5: error: Address of stack memory associated with local variable 'physical_properties_callback' returned to caller [clang-analyzer-core.StackAddressEscape,-warnings-as-errors]
  114 |     return *this;
      |     ^
/b/s/w/ir/cache/builder/engine/src/flutter/impeller/renderer/backend/vulkan/texture_vk_unittests.cc:77:24: note: Calling 'MakeContext'
   77 |   auto const context = MakeContext("Adreno (TM) 750", kQualcommVendorID);
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/b/s/w/ir/cache/builder/engine/src/flutter/impeller/renderer/backend/vulkan/texture_vk_unittests.cc:27:10: note: Calling 'MockVulkanContextBuilder::SetPhysicalPropertiesCallback'
   27 |   return MockVulkanContextBuilder()
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
   28 |       .SetPhysicalPropertiesCallback(
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   29 |           [device_name, vendor_id](VkPhysicalDevice device,
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   30 |                                    VkPhysicalDeviceProperties* prop) {
      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   31 |             prop->vendorID = vendor_id;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   32 |             device_name.copy(prop->deviceName, device_name.size());
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   33 |             prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   34 |           })
      |           ~~
../../../flutter/impeller/renderer/backend/vulkan/test/mock_vulkan.h:114:5: note: Address of stack memory associated with local variable 'physical_properties_callback' returned to caller
  110 |       std::function<void(VkPhysicalDevice device,
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  111 |                          VkPhysicalDeviceProperties* physicalProperties)>
      |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  112 |           physical_properties_callback) {
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  113 |     physical_properties_callback_ = std::move(physical_properties_callback);
  114 |     return *this;
      |     ^      ~~~~~
Suppressed 11894 warnings (11800 in non-user code, 94 NOLINT).
Use -header-filter=.* or leave it as default to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning treated as error

@flutter-dashboard

Copy link
Copy Markdown

This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@bdero
bdero force-pushed the bdero/adreno-manual-mip-provenance branch from e41dc15 to e695cbc Compare September 21, 2026 12:23
@bdero

bdero commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

@gaaclarke 👋

Rebased onto master and fixed the clang-tidy failure in e695cbc.

@gaaclarke
gaaclarke self-requested a review September 21, 2026 16:08
@gaaclarke

Copy link
Copy Markdown
Member

(don't forget to hit "Re-request review" or I might miss these =)

@bdero

bdero commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

Rebased onto master to pick up a fix for the unrelated ANGLE failure.

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to explain, lgtm!

@gaaclarke gaaclarke added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 22, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 22, 2026
@auto-submit

auto-submit Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/190186, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gaaclarke

Copy link
Copy Markdown
Member

I'm not sure why the presubmit is failing. I've filed an issue: #193175

The broken-mipmap workaround clamps every Vulkan sampler to the base mip
level so corrupt blit-generated chains are never read. That also collapsed
textures whose mip levels were uploaded by hand, which are valid. Skip the
clamp for those, detected via NeedsMipmapGeneration, so Flutter GPU manual
mip chains sample correctly while generated chains stay clamped.
Only textures whose mips came from the broken generation blit get clamped to the base level, instead of every sampler in the process.
The workaround now lives with the texture whose levels are corrupt. Drivers that generate bad mips get a base-level-only image view, used when sampling a texture those drivers mipped. Samplers, the sampler descriptor, and Flutter GPU no longer know about it.
clang-tidy traced a stack address escaping through the builder's callback. Plain function pointers carry no stack state, and a named builder keeps the reference it returns out of the caller.
@bdero
bdero force-pushed the bdero/adreno-manual-mip-provenance branch from c708e63 to 05407e9 Compare September 22, 2026 23:11
@bdero bdero added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App and removed CICD Run CI/CD labels Sep 22, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 23, 2026
Merged via the queue into flutter:master with commit e91c38b Sep 23, 2026
29 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from 🤔 Needs Triage to ✅ Done in Flutter GPU Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels.

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Android Impeller Vulkan renders cubemap-mip IBL reflections over-sharp

2 participants