Skip to content

Commit

Permalink
[Impeller] disable runtime mipmap generation on Adreno. (flutter#161257)
Browse files Browse the repository at this point in the history
I bypassed the ~compressor~ mip generation.

flutter#160441
flutter#159876
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.
  • Loading branch information
jonahwilliams authored Jan 7, 2025
1 parent ad5e1fe commit a3a4995
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ static void InsertImageMemoryBarrier(const vk::CommandBuffer& cmd,
cmd.pipelineBarrier(src_stage, dst_stage, {}, nullptr, nullptr, barrier);
}

BlitPassVK::BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer)
: command_buffer_(std::move(command_buffer)) {}
BlitPassVK::BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer,
const WorkaroundsVK& workarounds)
: command_buffer_(std::move(command_buffer)), workarounds_(workarounds) {}

BlitPassVK::~BlitPassVK() = default;

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

if (mip_count < 2u) {
if (mip_count < 2u || workarounds_.broken_mipmap_generation) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "flutter/impeller/base/config.h"
#include "impeller/geometry/rect.h"
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
#include "impeller/renderer/blit_pass.h"

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

std::shared_ptr<CommandBufferVK> command_buffer_;
const WorkaroundsVK workarounds_;

explicit BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer);
explicit BlitPassVK(std::shared_ptr<CommandBufferVK> command_buffer,
const WorkaroundsVK& workarounds);

// |BlitPass|
bool IsValid() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() {
if (!IsValid()) {
return nullptr;
}
auto pass = std::shared_ptr<BlitPassVK>(new BlitPassVK(shared_from_this()));
auto context = context_.lock();
if (!context) {
return nullptr;
}
auto pass = std::shared_ptr<BlitPassVK>(new BlitPassVK(
shared_from_this(), ContextVK::Cast(*context).GetWorkarounds()));
if (!pass->IsValid()) {
return nullptr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,8 @@ void ContextVK::Setup(Settings settings) {
// Apply workarounds for broken drivers.
auto driver_info =
std::make_unique<DriverInfoVK>(device_holder->physical_device);
WorkaroundsVK workarounds = GetWorkarounds(*driver_info);
caps->ApplyWorkarounds(workarounds);
workarounds_ = GetWorkaroundsFromDriverInfo(*driver_info);
caps->ApplyWorkarounds(workarounds_);

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

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

const WorkaroundsVK& ContextVK::GetWorkarounds() const {
return workarounds_;
}

} // namespace impeller
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "impeller/renderer/backend/vulkan/queue_vk.h"
#include "impeller/renderer/backend/vulkan/sampler_library_vk.h"
#include "impeller/renderer/backend/vulkan/shader_library_vk.h"
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
#include "impeller/renderer/capabilities.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/command_queue.h"
Expand Down Expand Up @@ -141,6 +142,8 @@ class ContextVK final : public Context,
// |Context|
void Shutdown() override;

const WorkaroundsVK& GetWorkarounds() const;

void SetOffscreenFormat(PixelFormat pixel_format);

template <typename T>
Expand Down Expand Up @@ -281,6 +284,7 @@ class ContextVK final : public Context,
std::shared_ptr<GPUTracerVK> gpu_tracer_;
std::shared_ptr<CommandQueue> command_queue_vk_;
std::shared_ptr<const IdleWaiter> idle_waiter_vk_;
WorkaroundsVK workarounds_;

using DescriptorPoolMap =
std::unordered_map<std::thread::id, std::shared_ptr<DescriptorPoolVK>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ bool CanBatchSubmitTest(std::string_view driver_name, bool qc = true) {
prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
})
.Build();
return !GetWorkarounds(*context->GetDriverInfo())
return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
.batch_submit_command_buffer_timeout;
}

Expand Down Expand Up @@ -110,7 +110,7 @@ bool CanUsePrimitiveRestartSubmitTest(std::string_view driver_name,
prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
})
.Build();
return !GetWorkarounds(*context->GetDriverInfo())
return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
.slow_primitive_restart_performance;
}

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

bool CanUseMipgeneration(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())
.broken_mipmap_generation;
}

TEST(DriverInfoVKTest, CanGenerateMipMaps) {
// Adreno no mips
EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 540", true));
EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 750", true));

// Mali A-OK
EXPECT_TRUE(CanUseMipgeneration("Mali-G51", false));
}

TEST(DriverInfoVKTest, DriverParsingMali) {
EXPECT_EQ(GetMaliVersion("Mali-G51-MORE STUFF"), MaliGPU::kG51);
EXPECT_EQ(GetMaliVersion("Mali-G51"), MaliGPU::kG51);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace impeller {

WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info) {
WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info) {
WorkaroundsVK workarounds;

const auto& adreno_gpu = driver_info.GetAdrenoGPUInfo();
Expand All @@ -15,6 +15,7 @@ WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info) {
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::kAdreno702) {
workarounds.batch_submit_command_buffer_timeout = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@ struct WorkaroundsVK {
/// requires the renderer to split up command buffers that could
/// be logically combined.
bool batch_submit_command_buffer_timeout = false;

/// Almost all Adreno series GPU (from 600 up to 800) have problems
/// generating mipmaps, resulting in corruption of the mip levels.
/// See:
/// * https://github.com/flutter/flutter/issues/160441
/// * https://github.com/flutter/flutter/issues/159876
/// * https://github.com/flutter/flutter/issues/160587
bool broken_mipmap_generation = false;
};
WorkaroundsVK GetWorkarounds(DriverInfoVK& driver_info);

WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK& driver_info);

} // namespace impeller

Expand Down

0 comments on commit a3a4995

Please sign in to comment.