Skip to content

Commit a3a4995

Browse files
author
Jonah Williams
authored
[Impeller] disable runtime mipmap generation on Adreno. (#161257)
I bypassed the ~compressor~ mip generation. flutter/flutter#160441 flutter/flutter#159876 flutter/flutter#160587 I have no idea how to get this to work. next thing to try is to force mip generation to happen in a square power of 2 texture, and then blit the individual mip regions onto the dest texture. For now, disable, as the issue is quite severe.
1 parent ad5e1fe commit a3a4995

File tree

8 files changed

+67
-12
lines changed

8 files changed

+67
-12
lines changed

engine/src/flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ static void InsertImageMemoryBarrier(const vk::CommandBuffer& cmd,
4444
cmd.pipelineBarrier(src_stage, dst_stage, {}, nullptr, nullptr, barrier);
4545
}
4646

47-
BlitPassVK::BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer)
48-
: command_buffer_(std::move(command_buffer)) {}
47+
BlitPassVK::BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer,
48+
const WorkaroundsVK& workarounds)
49+
: command_buffer_(std::move(command_buffer)), workarounds_(workarounds) {}
4950

5051
BlitPassVK::~BlitPassVK() = default;
5152

@@ -402,7 +403,7 @@ bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
402403
const auto size = src.GetTextureDescriptor().size;
403404
uint32_t mip_count = src.GetTextureDescriptor().mip_count;
404405

405-
if (mip_count < 2u) {
406+
if (mip_count < 2u || workarounds_.broken_mipmap_generation) {
406407
return true;
407408
}
408409

engine/src/flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "flutter/impeller/base/config.h"
99
#include "impeller/geometry/rect.h"
10+
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
1011
#include "impeller/renderer/blit_pass.h"
1112

1213
namespace impeller {
@@ -23,8 +24,10 @@ class BlitPassVK final : public BlitPass {
2324
friend class CommandBufferVK;
2425

2526
std::shared_ptr<CommandBufferVK> command_buffer_;
27+
const WorkaroundsVK workarounds_;
2628

27-
explicit BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer);
29+
explicit BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer,
30+
const WorkaroundsVK& workarounds);
2831

2932
// |BlitPass|
3033
bool IsValid() const override;

engine/src/flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() {
7272
if (!IsValid()) {
7373
return nullptr;
7474
}
75-
auto pass = std::shared_ptr<BlitPassVK>(new BlitPassVK(shared_from_this()));
75+
auto context = context_.lock();
76+
if (!context) {
77+
return nullptr;
78+
}
79+
auto pass = std::shared_ptr<BlitPassVK>(new BlitPassVK(
80+
shared_from_this(), ContextVK::Cast(*context).GetWorkarounds()));
7681
if (!pass->IsValid()) {
7782
return nullptr;
7883
}

engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ void ContextVK::Setup(Settings settings) {
462462
// Apply workarounds for broken drivers.
463463
auto driver_info =
464464
std::make_unique<DriverInfoVK>(device_holder->physical_device);
465-
WorkaroundsVK workarounds = GetWorkarounds(*driver_info);
466-
caps->ApplyWorkarounds(workarounds);
465+
workarounds_ = GetWorkaroundsFromDriverInfo(*driver_info);
466+
caps->ApplyWorkarounds(workarounds_);
467467

468468
device_holder_ = std::move(device_holder);
469469
idle_waiter_vk_ = std::make_shared<IdleWaiterVK>(device_holder_);
@@ -484,7 +484,7 @@ void ContextVK::Setup(Settings settings) {
484484
device_name_ = std::string(physical_device_properties.deviceName);
485485
command_queue_vk_ = std::make_shared<CommandQueueVK>(weak_from_this());
486486
should_disable_surface_control_ = settings.disable_surface_control;
487-
should_batch_cmd_buffers_ = !workarounds.batch_submit_command_buffer_timeout;
487+
should_batch_cmd_buffers_ = !workarounds_.batch_submit_command_buffer_timeout;
488488
is_valid_ = true;
489489

490490
// Create the GPU Tracer later because it depends on state from
@@ -741,4 +741,8 @@ bool ContextVK::SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer) {
741741
return EnqueueCommandBuffer(std::move(cmd_buffer));
742742
}
743743

744+
const WorkaroundsVK& ContextVK::GetWorkarounds() const {
745+
return workarounds_;
746+
}
747+
744748
} // namespace impeller

engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "impeller/renderer/backend/vulkan/queue_vk.h"
2222
#include "impeller/renderer/backend/vulkan/sampler_library_vk.h"
2323
#include "impeller/renderer/backend/vulkan/shader_library_vk.h"
24+
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
2425
#include "impeller/renderer/capabilities.h"
2526
#include "impeller/renderer/command_buffer.h"
2627
#include "impeller/renderer/command_queue.h"
@@ -141,6 +142,8 @@ class ContextVK final : public Context,
141142
// |Context|
142143
void Shutdown() override;
143144

145+
const WorkaroundsVK& GetWorkarounds() const;
146+
144147
void SetOffscreenFormat(PixelFormat pixel_format);
145148

146149
template <typename T>
@@ -281,6 +284,7 @@ class ContextVK final : public Context,
281284
std::shared_ptr<GPUTracerVK> gpu_tracer_;
282285
std::shared_ptr<CommandQueue> command_queue_vk_;
283286
std::shared_ptr<const IdleWaiter> idle_waiter_vk_;
287+
WorkaroundsVK workarounds_;
284288

285289
using DescriptorPoolMap =
286290
std::unordered_map<std::thread::id, std::shared_ptr<DescriptorPoolVK>>;

engine/src/flutter/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ bool CanBatchSubmitTest(std::string_view driver_name, bool qc = true) {
8282
prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
8383
})
8484
.Build();
85-
return !GetWorkarounds(*context->GetDriverInfo())
85+
return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
8686
.batch_submit_command_buffer_timeout;
8787
}
8888

@@ -110,7 +110,7 @@ bool CanUsePrimitiveRestartSubmitTest(std::string_view driver_name,
110110
prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
111111
})
112112
.Build();
113-
return !GetWorkarounds(*context->GetDriverInfo())
113+
return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
114114
.slow_primitive_restart_performance;
115115
}
116116

@@ -123,6 +123,34 @@ TEST(DriverInfoVKTest, CanUsePrimitiveRestart) {
123123
EXPECT_TRUE(CanUsePrimitiveRestartSubmitTest("Mali-G51", false));
124124
}
125125

126+
bool CanUseMipgeneration(std::string_view driver_name, bool qc = true) {
127+
auto const context =
128+
MockVulkanContextBuilder()
129+
.SetPhysicalPropertiesCallback(
130+
[&driver_name, qc](VkPhysicalDevice device,
131+
VkPhysicalDeviceProperties* prop) {
132+
if (qc) {
133+
prop->vendorID = 0x168C; // Qualcomm
134+
} else {
135+
prop->vendorID = 0x13B5; // ARM
136+
}
137+
driver_name.copy(prop->deviceName, driver_name.size());
138+
prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
139+
})
140+
.Build();
141+
return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
142+
.broken_mipmap_generation;
143+
}
144+
145+
TEST(DriverInfoVKTest, CanGenerateMipMaps) {
146+
// Adreno no mips
147+
EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 540", true));
148+
EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 750", true));
149+
150+
// Mali A-OK
151+
EXPECT_TRUE(CanUseMipgeneration("Mali-G51", false));
152+
}
153+
126154
TEST(DriverInfoVKTest, DriverParsingMali) {
127155
EXPECT_EQ(GetMaliVersion("Mali-G51-MORE STUFF"), MaliGPU::kG51);
128156
EXPECT_EQ(GetMaliVersion("Mali-G51"), MaliGPU::kG51);

engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace impeller {
88

9-
WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info) {
9+
WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info) {
1010
WorkaroundsVK workarounds;
1111

1212
const auto& adreno_gpu = driver_info.GetAdrenoGPUInfo();
@@ -15,6 +15,7 @@ WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info) {
1515
workarounds.batch_submit_command_buffer_timeout = true;
1616
if (adreno_gpu.has_value()) {
1717
workarounds.slow_primitive_restart_performance = true;
18+
workarounds.broken_mipmap_generation = true;
1819

1920
if (adreno_gpu.value() >= AdrenoGPU::kAdreno702) {
2021
workarounds.batch_submit_command_buffer_timeout = false;

engine/src/flutter/impeller/renderer/backend/vulkan/workarounds_vk.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,17 @@ struct WorkaroundsVK {
2222
/// requires the renderer to split up command buffers that could
2323
/// be logically combined.
2424
bool batch_submit_command_buffer_timeout = false;
25+
26+
/// Almost all Adreno series GPU (from 600 up to 800) have problems
27+
/// generating mipmaps, resulting in corruption of the mip levels.
28+
/// See:
29+
/// * https://github.com/flutter/flutter/issues/160441
30+
/// * https://github.com/flutter/flutter/issues/159876
31+
/// * https://github.com/flutter/flutter/issues/160587
32+
bool broken_mipmap_generation = false;
2533
};
26-
WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info);
34+
35+
WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info);
2736

2837
} // namespace impeller
2938

0 commit comments

Comments
 (0)