[Impeller] disable runtime mipmap generation on Adreno. (#161257)
I bypassed the ~compressor~ mip generation. https://github.com/flutter/flutter/issues/160441 https://github.com/flutter/flutter/issues/159876 https://github.com/flutter/flutter/issues/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.
This commit is contained in:
parent
ad5e1fe300
commit
a3a4995607
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_);
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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"
|
||||
@ -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>
|
||||
@ -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>>;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
@ -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();
|
||||
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user