Skip to content

Commit a7e276a

Browse files
author
Jonah Williams
authored
[Impeller] add capability check for extended range formats. (#164817)
Fixes flutter/flutter#164794 We support devices that do not support XR formats. If we try to decode to an XR format this will fail at runtime.
1 parent 6d6d791 commit a7e276a

File tree

11 files changed

+61
-5
lines changed

11 files changed

+61
-5
lines changed

engine/src/flutter/impeller/renderer/backend/gles/capabilities_gles.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ bool CapabilitiesGLES::SupportsPrimitiveRestart() const {
219219
return false;
220220
}
221221

222+
bool CapabilitiesGLES::SupportsExtendedRangeFormats() const {
223+
return false;
224+
}
225+
222226
PixelFormat CapabilitiesGLES::GetDefaultGlyphAtlasFormat() const {
223227
return default_glyph_atlas_format_;
224228
}

engine/src/flutter/impeller/renderer/backend/gles/capabilities_gles.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ class CapabilitiesGLES final
116116
// |Capabilities|
117117
bool SupportsPrimitiveRestart() const override;
118118

119+
// |Capabilities|
120+
bool SupportsExtendedRangeFormats() const override;
121+
119122
// |Capabilities|
120123
PixelFormat GetDefaultColorFormat() const override;
121124

engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
5252
return supports_subgroups;
5353
}
5454

55+
// See "Extended Range and wide color pixel formats" in the metal feature set
56+
// tables.
57+
static bool DeviceSupportsExtendedRangeFormats(id<MTLDevice> device) {
58+
if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
59+
return [device supportsFamily:MTLGPUFamilyApple3];
60+
}
61+
return false;
62+
}
63+
5564
static std::unique_ptr<Capabilities> InferMetalCapabilities(
5665
id<MTLDevice> device,
5766
PixelFormat color_format) {
@@ -71,6 +80,8 @@ static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
7180
.SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
7281
.SetSupportsTriangleFan(false)
7382
.SetMaximumRenderPassAttachmentSize(DeviceMaxTextureSizeSupported(device))
83+
.SetSupportsExtendedRangeFormats(
84+
DeviceSupportsExtendedRangeFormats(device))
7485
.Build();
7586
}
7687

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,4 +798,8 @@ bool CapabilitiesVK::SupportsExternalSemaphoreExtensions() const {
798798
return supports_external_fence_and_semaphore_;
799799
}
800800

801+
bool CapabilitiesVK::SupportsExtendedRangeFormats() const {
802+
return false;
803+
}
804+
801805
} // namespace impeller

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ class CapabilitiesVK final : public Capabilities,
260260
// |Capabilities|
261261
bool SupportsPrimitiveRestart() const override;
262262

263+
// |Capabilities|
264+
bool SupportsExtendedRangeFormats() const override;
265+
263266
// |Capabilities|
264267
PixelFormat GetDefaultColorFormat() const override;
265268

engine/src/flutter/impeller/renderer/capabilities.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ class StandardCapabilities final : public Capabilities {
9191
// |Capabilities|
9292
bool SupportsPrimitiveRestart() const override { return true; }
9393

94+
// |Capabilities|
95+
bool SupportsExtendedRangeFormats() const override {
96+
return supports_extended_range_formats_;
97+
}
98+
9499
private:
95100
StandardCapabilities(bool supports_offscreen_msaa,
96101
bool supports_ssbo,
@@ -102,6 +107,7 @@ class StandardCapabilities final : public Capabilities {
102107
bool supports_decal_sampler_address_mode,
103108
bool supports_device_transient_textures,
104109
bool supports_triangle_fan,
110+
bool supports_extended_range_formats,
105111
PixelFormat default_color_format,
106112
PixelFormat default_stencil_format,
107113
PixelFormat default_depth_stencil_format,
@@ -118,6 +124,7 @@ class StandardCapabilities final : public Capabilities {
118124
supports_decal_sampler_address_mode),
119125
supports_device_transient_textures_(supports_device_transient_textures),
120126
supports_triangle_fan_(supports_triangle_fan),
127+
supports_extended_range_formats_(supports_extended_range_formats),
121128
default_color_format_(default_color_format),
122129
default_stencil_format_(default_stencil_format),
123130
default_depth_stencil_format_(default_depth_stencil_format),
@@ -137,6 +144,7 @@ class StandardCapabilities final : public Capabilities {
137144
bool supports_decal_sampler_address_mode_ = false;
138145
bool supports_device_transient_textures_ = false;
139146
bool supports_triangle_fan_ = false;
147+
bool supports_extended_range_formats_ = false;
140148
PixelFormat default_color_format_ = PixelFormat::kUnknown;
141149
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
142150
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
@@ -238,6 +246,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize(
238246
return *this;
239247
}
240248

249+
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsExtendedRangeFormats(
250+
bool value) {
251+
supports_extended_range_formats_ = value;
252+
return *this;
253+
}
254+
241255
std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
242256
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
243257
supports_offscreen_msaa_, //
@@ -250,6 +264,7 @@ std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
250264
supports_decal_sampler_address_mode_, //
251265
supports_device_transient_textures_, //
252266
supports_triangle_fan_, //
267+
supports_extended_range_formats_, //
253268
default_color_format_.value_or(PixelFormat::kUnknown), //
254269
default_stencil_format_.value_or(PixelFormat::kUnknown), //
255270
default_depth_stencil_format_.value_or(PixelFormat::kUnknown), //

engine/src/flutter/impeller/renderer/capabilities.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ class Capabilities {
116116
/// Note that this may be smaller than the maximum allocatable texture size.
117117
virtual ISize GetMaximumRenderPassAttachmentSize() const = 0;
118118

119+
/// @brief Whether the XR formats are supported on this device.
120+
///
121+
/// This is only ever true for iOS and macOS devices. We may need
122+
/// to revisit this API when approaching wide gamut rendering for
123+
/// Vulkan and GLES.
124+
virtual bool SupportsExtendedRangeFormats() const = 0;
125+
119126
protected:
120127
Capabilities();
121128

@@ -154,6 +161,8 @@ class CapabilitiesBuilder {
154161

155162
CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value);
156163

164+
CapabilitiesBuilder& SetSupportsExtendedRangeFormats(bool value);
165+
157166
CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value);
158167

159168
CapabilitiesBuilder& SetSupportsTriangleFan(bool value);
@@ -173,6 +182,7 @@ class CapabilitiesBuilder {
173182
bool supports_decal_sampler_address_mode_ = false;
174183
bool supports_device_transient_textures_ = false;
175184
bool supports_triangle_fan_ = false;
185+
bool supports_extended_range_formats_ = false;
176186
std::optional<PixelFormat> default_color_format_ = std::nullopt;
177187
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
178188
std::optional<PixelFormat> default_depth_stencil_format_ = std::nullopt;

engine/src/flutter/impeller/renderer/capabilities_unittests.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ CAPABILITY_TEST(SupportsReadFromResolve, false);
2828
CAPABILITY_TEST(SupportsDecalSamplerAddressMode, false);
2929
CAPABILITY_TEST(SupportsDeviceTransientTextures, false);
3030
CAPABILITY_TEST(SupportsTriangleFan, false);
31+
CAPABILITY_TEST(SupportsExtendedRangeFormats, false);
3132

3233
TEST(CapabilitiesTest, DefaultColorFormat) {
3334
auto defaults = CapabilitiesBuilder().Build();

engine/src/flutter/impeller/renderer/testing/mocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ class MockCapabilities : public Capabilities {
223223
MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override));
224224
MOCK_METHOD(bool, SupportsTriangleFan, (), (const override));
225225
MOCK_METHOD(bool, SupportsPrimitiveRestart, (), (const override));
226+
MOCK_METHOD(bool, SupportsExtendedRangeFormats, (), (const override));
226227
MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override));
227228
MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override));
228229
MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override));

engine/src/flutter/lib/ui/painting/image_decoder_impeller.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ ImageDecoderImpeller::ImageDecoderImpeller(
8080
const TaskRunners& runners,
8181
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
8282
const fml::WeakPtr<IOManager>& io_manager,
83-
bool supports_wide_gamut,
83+
bool wide_gamut_enabled,
8484
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
8585
: ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
86-
supports_wide_gamut_(supports_wide_gamut),
86+
wide_gamut_enabled_(wide_gamut_enabled),
8787
gpu_disabled_switch_(gpu_disabled_switch) {
8888
std::promise<std::shared_ptr<impeller::Context>> context_promise;
8989
context_ = context_promise.get_future();
@@ -526,7 +526,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
526526
target_size = SkISize::Make(target_width, target_height), //
527527
io_runner = runners_.GetIOTaskRunner(), //
528528
result,
529-
supports_wide_gamut = supports_wide_gamut_, //
529+
wide_gamut_enabled = wide_gamut_enabled_, //
530530
gpu_disabled_switch = gpu_disabled_switch_]() {
531531
#if FML_OS_IOS_SIMULATOR
532532
// No-op backend.
@@ -545,7 +545,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
545545
// Always decompress on the concurrent runner.
546546
auto bitmap_result = DecompressTexture(
547547
raw_descriptor, target_size, max_size_supported,
548-
/*supports_wide_gamut=*/supports_wide_gamut,
548+
/*supports_wide_gamut=*/wide_gamut_enabled &&
549+
context->GetCapabilities()->SupportsExtendedRangeFormats(),
549550
context->GetCapabilities(), context->GetResourceAllocator());
550551
if (!bitmap_result.device_buffer) {
551552
result(nullptr, bitmap_result.decode_error);

0 commit comments

Comments
 (0)