Skip to content

Commit fe257cb

Browse files
author
Jonah Williams
authored
[Impeller] when mips are disabled, also disable from sampler options. (#161765)
If we have disabled mipmap generation on a platform due to GPU driver bugs, make sure that all sampling options used declare that only the base mip level should be read. Otherwise we can end up sampling from unpopulated mip levels.
1 parent 5e24ac8 commit fe257cb

File tree

6 files changed

+61
-4
lines changed

6 files changed

+61
-4
lines changed

engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impeller_component("vulkan_unittests") {
2424
"test/mock_vulkan.cc",
2525
"test/mock_vulkan.h",
2626
"test/mock_vulkan_unittests.cc",
27+
"test/sampler_library_vk_unittests.cc",
2728
"test/swapchain_unittests.cc",
2829
]
2930
deps = [

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ void ContextVK::Setup(Settings settings) {
464464
std::make_unique<DriverInfoVK>(device_holder->physical_device);
465465
workarounds_ = GetWorkaroundsFromDriverInfo(*driver_info);
466466
caps->ApplyWorkarounds(workarounds_);
467+
sampler_library->ApplyWorkarounds(workarounds_);
467468

468469
device_holder_ = std::move(device_holder);
469470
idle_waiter_vk_ = std::make_shared<IdleWaiterVK>(device_holder_);

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "impeller/renderer/backend/vulkan/sampler_library_vk.h"
66

7+
#include "impeller/core/formats.h"
78
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
89

910
namespace impeller {
@@ -14,9 +15,18 @@ SamplerLibraryVK::SamplerLibraryVK(
1415

1516
SamplerLibraryVK::~SamplerLibraryVK() = default;
1617

18+
void SamplerLibraryVK::ApplyWorkarounds(const WorkaroundsVK& workarounds) {
19+
mips_disabled_workaround_ = workarounds.broken_mipmap_generation;
20+
}
21+
1722
raw_ptr<const Sampler> SamplerLibraryVK::GetSampler(
1823
const SamplerDescriptor& desc) {
19-
uint64_t p_key = SamplerDescriptor::ToKey(desc);
24+
SamplerDescriptor desc_copy = desc;
25+
if (mips_disabled_workaround_) {
26+
desc_copy.mip_filter = MipFilter::kBase;
27+
}
28+
29+
uint64_t p_key = SamplerDescriptor::ToKey(desc_copy);
2030
for (const auto& [key, value] : samplers_) {
2131
if (key == p_key) {
2232
return raw_ptr(value);
@@ -27,7 +37,8 @@ raw_ptr<const Sampler> SamplerLibraryVK::GetSampler(
2737
return raw_ptr<const Sampler>(nullptr);
2838
}
2939
samplers_.push_back(std::make_pair(
30-
p_key, std::make_shared<SamplerVK>(device_holder->GetDevice(), desc)));
40+
p_key,
41+
std::make_shared<SamplerVK>(device_holder->GetDevice(), desc_copy)));
3142
return raw_ptr(samplers_.back().second);
3243
}
3344

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "impeller/core/sampler.h"
1010
#include "impeller/core/sampler_descriptor.h"
1111
#include "impeller/renderer/backend/vulkan/device_holder_vk.h"
12+
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
1213
#include "impeller/renderer/sampler_library.h"
1314

1415
namespace impeller {
@@ -20,13 +21,16 @@ class SamplerLibraryVK final
2021
// |SamplerLibrary|
2122
~SamplerLibraryVK() override;
2223

24+
explicit SamplerLibraryVK(const std::weak_ptr<DeviceHolderVK>& device_holder);
25+
26+
void ApplyWorkarounds(const WorkaroundsVK& workarounds);
27+
2328
private:
2429
friend class ContextVK;
2530

2631
std::weak_ptr<DeviceHolderVK> device_holder_;
2732
std::vector<std::pair<uint64_t, std::shared_ptr<const Sampler>>> samplers_;
28-
29-
explicit SamplerLibraryVK(const std::weak_ptr<DeviceHolderVK>& device_holder);
33+
bool mips_disabled_workaround_ = false;
3034

3135
// |SamplerLibrary|
3236
raw_ptr<const Sampler> GetSampler(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class SamplerVK final : public Sampler, public BackendCast<SamplerVK, Sampler> {
3737
const vk::Device device_;
3838
SharedHandleVK<vk::Sampler> sampler_;
3939
std::shared_ptr<YUVConversionVK> yuv_conversion_;
40+
bool mips_disabled_workaround_ = false;
4041
bool is_valid_ = false;
4142

4243
SamplerVK(const SamplerVK&) = delete;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include <memory>
6+
#include "flutter/testing/testing.h" // IWYU pragma: keep
7+
#include "gtest/gtest.h"
8+
#include "impeller/core/formats.h"
9+
#include "impeller/core/sampler_descriptor.h"
10+
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
11+
#include "impeller/renderer/backend/vulkan/sampler_library_vk.h"
12+
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
13+
#include "impeller/renderer/backend/vulkan/workarounds_vk.h"
14+
15+
namespace impeller {
16+
namespace testing {
17+
18+
TEST(SamplerLibraryVK, WorkaroundsCanDisableReadingFromMipLevels) {
19+
auto const context = MockVulkanContextBuilder().Build();
20+
21+
auto library_vk =
22+
std::make_shared<SamplerLibraryVK>(context->GetDeviceHolder());
23+
std::shared_ptr<SamplerLibrary> library = library_vk;
24+
25+
SamplerDescriptor desc;
26+
desc.mip_filter = MipFilter::kLinear;
27+
28+
auto sampler = library->GetSampler(desc);
29+
EXPECT_EQ(sampler->GetDescriptor().mip_filter, MipFilter::kLinear);
30+
31+
// Apply mips disabled workaround.
32+
library_vk->ApplyWorkarounds(WorkaroundsVK{.broken_mipmap_generation = true});
33+
34+
sampler = library->GetSampler(desc);
35+
EXPECT_EQ(sampler->GetDescriptor().mip_filter, MipFilter::kBase);
36+
}
37+
38+
} // namespace testing
39+
} // namespace impeller

0 commit comments

Comments
 (0)