[Impeller] add capability check for extended range formats. (#164817)
Fixes https://github.com/flutter/flutter/issues/164794 We support devices that do not support XR formats. If we try to decode to an XR format this will fail at runtime.
This commit is contained in:
parent
6d6d7914f9
commit
a7e276a20d
@ -219,6 +219,10 @@ bool CapabilitiesGLES::SupportsPrimitiveRestart() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CapabilitiesGLES::SupportsExtendedRangeFormats() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
PixelFormat CapabilitiesGLES::GetDefaultGlyphAtlasFormat() const {
|
||||
return default_glyph_atlas_format_;
|
||||
}
|
||||
|
@ -116,6 +116,9 @@ class CapabilitiesGLES final
|
||||
// |Capabilities|
|
||||
bool SupportsPrimitiveRestart() const override;
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsExtendedRangeFormats() const override;
|
||||
|
||||
// |Capabilities|
|
||||
PixelFormat GetDefaultColorFormat() const override;
|
||||
|
||||
|
@ -52,6 +52,15 @@ static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
|
||||
return supports_subgroups;
|
||||
}
|
||||
|
||||
// See "Extended Range and wide color pixel formats" in the metal feature set
|
||||
// tables.
|
||||
static bool DeviceSupportsExtendedRangeFormats(id<MTLDevice> device) {
|
||||
if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
|
||||
return [device supportsFamily:MTLGPUFamilyApple3];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
id<MTLDevice> device,
|
||||
PixelFormat color_format) {
|
||||
@ -71,6 +80,8 @@ static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
.SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
|
||||
.SetSupportsTriangleFan(false)
|
||||
.SetMaximumRenderPassAttachmentSize(DeviceMaxTextureSizeSupported(device))
|
||||
.SetSupportsExtendedRangeFormats(
|
||||
DeviceSupportsExtendedRangeFormats(device))
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
@ -798,4 +798,8 @@ bool CapabilitiesVK::SupportsExternalSemaphoreExtensions() const {
|
||||
return supports_external_fence_and_semaphore_;
|
||||
}
|
||||
|
||||
bool CapabilitiesVK::SupportsExtendedRangeFormats() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -260,6 +260,9 @@ class CapabilitiesVK final : public Capabilities,
|
||||
// |Capabilities|
|
||||
bool SupportsPrimitiveRestart() const override;
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsExtendedRangeFormats() const override;
|
||||
|
||||
// |Capabilities|
|
||||
PixelFormat GetDefaultColorFormat() const override;
|
||||
|
||||
|
@ -91,6 +91,11 @@ class StandardCapabilities final : public Capabilities {
|
||||
// |Capabilities|
|
||||
bool SupportsPrimitiveRestart() const override { return true; }
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsExtendedRangeFormats() const override {
|
||||
return supports_extended_range_formats_;
|
||||
}
|
||||
|
||||
private:
|
||||
StandardCapabilities(bool supports_offscreen_msaa,
|
||||
bool supports_ssbo,
|
||||
@ -102,6 +107,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
bool supports_decal_sampler_address_mode,
|
||||
bool supports_device_transient_textures,
|
||||
bool supports_triangle_fan,
|
||||
bool supports_extended_range_formats,
|
||||
PixelFormat default_color_format,
|
||||
PixelFormat default_stencil_format,
|
||||
PixelFormat default_depth_stencil_format,
|
||||
@ -118,6 +124,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
supports_decal_sampler_address_mode),
|
||||
supports_device_transient_textures_(supports_device_transient_textures),
|
||||
supports_triangle_fan_(supports_triangle_fan),
|
||||
supports_extended_range_formats_(supports_extended_range_formats),
|
||||
default_color_format_(default_color_format),
|
||||
default_stencil_format_(default_stencil_format),
|
||||
default_depth_stencil_format_(default_depth_stencil_format),
|
||||
@ -137,6 +144,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
bool supports_decal_sampler_address_mode_ = false;
|
||||
bool supports_device_transient_textures_ = false;
|
||||
bool supports_triangle_fan_ = false;
|
||||
bool supports_extended_range_formats_ = false;
|
||||
PixelFormat default_color_format_ = PixelFormat::kUnknown;
|
||||
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
|
||||
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
|
||||
@ -238,6 +246,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize(
|
||||
return *this;
|
||||
}
|
||||
|
||||
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsExtendedRangeFormats(
|
||||
bool value) {
|
||||
supports_extended_range_formats_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
|
||||
supports_offscreen_msaa_, //
|
||||
@ -250,6 +264,7 @@ std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||
supports_decal_sampler_address_mode_, //
|
||||
supports_device_transient_textures_, //
|
||||
supports_triangle_fan_, //
|
||||
supports_extended_range_formats_, //
|
||||
default_color_format_.value_or(PixelFormat::kUnknown), //
|
||||
default_stencil_format_.value_or(PixelFormat::kUnknown), //
|
||||
default_depth_stencil_format_.value_or(PixelFormat::kUnknown), //
|
||||
|
@ -116,6 +116,13 @@ class Capabilities {
|
||||
/// Note that this may be smaller than the maximum allocatable texture size.
|
||||
virtual ISize GetMaximumRenderPassAttachmentSize() const = 0;
|
||||
|
||||
/// @brief Whether the XR formats are supported on this device.
|
||||
///
|
||||
/// This is only ever true for iOS and macOS devices. We may need
|
||||
/// to revisit this API when approaching wide gamut rendering for
|
||||
/// Vulkan and GLES.
|
||||
virtual bool SupportsExtendedRangeFormats() const = 0;
|
||||
|
||||
protected:
|
||||
Capabilities();
|
||||
|
||||
@ -154,6 +161,8 @@ class CapabilitiesBuilder {
|
||||
|
||||
CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsExtendedRangeFormats(bool value);
|
||||
|
||||
CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsTriangleFan(bool value);
|
||||
@ -173,6 +182,7 @@ class CapabilitiesBuilder {
|
||||
bool supports_decal_sampler_address_mode_ = false;
|
||||
bool supports_device_transient_textures_ = false;
|
||||
bool supports_triangle_fan_ = false;
|
||||
bool supports_extended_range_formats_ = false;
|
||||
std::optional<PixelFormat> default_color_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_depth_stencil_format_ = std::nullopt;
|
||||
|
@ -28,6 +28,7 @@ CAPABILITY_TEST(SupportsReadFromResolve, false);
|
||||
CAPABILITY_TEST(SupportsDecalSamplerAddressMode, false);
|
||||
CAPABILITY_TEST(SupportsDeviceTransientTextures, false);
|
||||
CAPABILITY_TEST(SupportsTriangleFan, false);
|
||||
CAPABILITY_TEST(SupportsExtendedRangeFormats, false);
|
||||
|
||||
TEST(CapabilitiesTest, DefaultColorFormat) {
|
||||
auto defaults = CapabilitiesBuilder().Build();
|
||||
|
@ -223,6 +223,7 @@ class MockCapabilities : public Capabilities {
|
||||
MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override));
|
||||
MOCK_METHOD(bool, SupportsTriangleFan, (), (const override));
|
||||
MOCK_METHOD(bool, SupportsPrimitiveRestart, (), (const override));
|
||||
MOCK_METHOD(bool, SupportsExtendedRangeFormats, (), (const override));
|
||||
MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override));
|
||||
MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override));
|
||||
MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override));
|
||||
|
@ -80,10 +80,10 @@ ImageDecoderImpeller::ImageDecoderImpeller(
|
||||
const TaskRunners& runners,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
bool supports_wide_gamut,
|
||||
bool wide_gamut_enabled,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
||||
: ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
|
||||
supports_wide_gamut_(supports_wide_gamut),
|
||||
wide_gamut_enabled_(wide_gamut_enabled),
|
||||
gpu_disabled_switch_(gpu_disabled_switch) {
|
||||
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
||||
context_ = context_promise.get_future();
|
||||
@ -526,7 +526,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
||||
target_size = SkISize::Make(target_width, target_height), //
|
||||
io_runner = runners_.GetIOTaskRunner(), //
|
||||
result,
|
||||
supports_wide_gamut = supports_wide_gamut_, //
|
||||
wide_gamut_enabled = wide_gamut_enabled_, //
|
||||
gpu_disabled_switch = gpu_disabled_switch_]() {
|
||||
#if FML_OS_IOS_SIMULATOR
|
||||
// No-op backend.
|
||||
@ -545,7 +545,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
||||
// Always decompress on the concurrent runner.
|
||||
auto bitmap_result = DecompressTexture(
|
||||
raw_descriptor, target_size, max_size_supported,
|
||||
/*supports_wide_gamut=*/supports_wide_gamut,
|
||||
/*supports_wide_gamut=*/wide_gamut_enabled &&
|
||||
context->GetCapabilities()->SupportsExtendedRangeFormats(),
|
||||
context->GetCapabilities(), context->GetResourceAllocator());
|
||||
if (!bitmap_result.device_buffer) {
|
||||
result(nullptr, bitmap_result.decode_error);
|
||||
|
@ -101,7 +101,10 @@ class ImageDecoderImpeller final : public ImageDecoder {
|
||||
private:
|
||||
using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
|
||||
FutureContext context_;
|
||||
const bool supports_wide_gamut_;
|
||||
|
||||
/// Whether wide gamut rendering has been enabled (but not necessarily whether
|
||||
/// or not it is supported).
|
||||
const bool wide_gamut_enabled_;
|
||||
std::shared_ptr<fml::SyncSwitch> gpu_disabled_switch_;
|
||||
|
||||
/// Only call this method if the GPU is available.
|
||||
|
Loading…
x
Reference in New Issue
Block a user