[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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CapabilitiesGLES::SupportsExtendedRangeFormats() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PixelFormat CapabilitiesGLES::GetDefaultGlyphAtlasFormat() const {
|
PixelFormat CapabilitiesGLES::GetDefaultGlyphAtlasFormat() const {
|
||||||
return default_glyph_atlas_format_;
|
return default_glyph_atlas_format_;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,9 @@ class CapabilitiesGLES final
|
|||||||
// |Capabilities|
|
// |Capabilities|
|
||||||
bool SupportsPrimitiveRestart() const override;
|
bool SupportsPrimitiveRestart() const override;
|
||||||
|
|
||||||
|
// |Capabilities|
|
||||||
|
bool SupportsExtendedRangeFormats() const override;
|
||||||
|
|
||||||
// |Capabilities|
|
// |Capabilities|
|
||||||
PixelFormat GetDefaultColorFormat() const override;
|
PixelFormat GetDefaultColorFormat() const override;
|
||||||
|
|
||||||
|
@ -52,6 +52,15 @@ static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
|
|||||||
return supports_subgroups;
|
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(
|
static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||||
id<MTLDevice> device,
|
id<MTLDevice> device,
|
||||||
PixelFormat color_format) {
|
PixelFormat color_format) {
|
||||||
@ -71,6 +80,8 @@ static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
|||||||
.SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
|
.SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
|
||||||
.SetSupportsTriangleFan(false)
|
.SetSupportsTriangleFan(false)
|
||||||
.SetMaximumRenderPassAttachmentSize(DeviceMaxTextureSizeSupported(device))
|
.SetMaximumRenderPassAttachmentSize(DeviceMaxTextureSizeSupported(device))
|
||||||
|
.SetSupportsExtendedRangeFormats(
|
||||||
|
DeviceSupportsExtendedRangeFormats(device))
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,4 +798,8 @@ bool CapabilitiesVK::SupportsExternalSemaphoreExtensions() const {
|
|||||||
return supports_external_fence_and_semaphore_;
|
return supports_external_fence_and_semaphore_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CapabilitiesVK::SupportsExtendedRangeFormats() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace impeller
|
} // namespace impeller
|
||||||
|
@ -260,6 +260,9 @@ class CapabilitiesVK final : public Capabilities,
|
|||||||
// |Capabilities|
|
// |Capabilities|
|
||||||
bool SupportsPrimitiveRestart() const override;
|
bool SupportsPrimitiveRestart() const override;
|
||||||
|
|
||||||
|
// |Capabilities|
|
||||||
|
bool SupportsExtendedRangeFormats() const override;
|
||||||
|
|
||||||
// |Capabilities|
|
// |Capabilities|
|
||||||
PixelFormat GetDefaultColorFormat() const override;
|
PixelFormat GetDefaultColorFormat() const override;
|
||||||
|
|
||||||
|
@ -91,6 +91,11 @@ class StandardCapabilities final : public Capabilities {
|
|||||||
// |Capabilities|
|
// |Capabilities|
|
||||||
bool SupportsPrimitiveRestart() const override { return true; }
|
bool SupportsPrimitiveRestart() const override { return true; }
|
||||||
|
|
||||||
|
// |Capabilities|
|
||||||
|
bool SupportsExtendedRangeFormats() const override {
|
||||||
|
return supports_extended_range_formats_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StandardCapabilities(bool supports_offscreen_msaa,
|
StandardCapabilities(bool supports_offscreen_msaa,
|
||||||
bool supports_ssbo,
|
bool supports_ssbo,
|
||||||
@ -102,6 +107,7 @@ class StandardCapabilities final : public Capabilities {
|
|||||||
bool supports_decal_sampler_address_mode,
|
bool supports_decal_sampler_address_mode,
|
||||||
bool supports_device_transient_textures,
|
bool supports_device_transient_textures,
|
||||||
bool supports_triangle_fan,
|
bool supports_triangle_fan,
|
||||||
|
bool supports_extended_range_formats,
|
||||||
PixelFormat default_color_format,
|
PixelFormat default_color_format,
|
||||||
PixelFormat default_stencil_format,
|
PixelFormat default_stencil_format,
|
||||||
PixelFormat default_depth_stencil_format,
|
PixelFormat default_depth_stencil_format,
|
||||||
@ -118,6 +124,7 @@ class StandardCapabilities final : public Capabilities {
|
|||||||
supports_decal_sampler_address_mode),
|
supports_decal_sampler_address_mode),
|
||||||
supports_device_transient_textures_(supports_device_transient_textures),
|
supports_device_transient_textures_(supports_device_transient_textures),
|
||||||
supports_triangle_fan_(supports_triangle_fan),
|
supports_triangle_fan_(supports_triangle_fan),
|
||||||
|
supports_extended_range_formats_(supports_extended_range_formats),
|
||||||
default_color_format_(default_color_format),
|
default_color_format_(default_color_format),
|
||||||
default_stencil_format_(default_stencil_format),
|
default_stencil_format_(default_stencil_format),
|
||||||
default_depth_stencil_format_(default_depth_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_decal_sampler_address_mode_ = false;
|
||||||
bool supports_device_transient_textures_ = false;
|
bool supports_device_transient_textures_ = false;
|
||||||
bool supports_triangle_fan_ = false;
|
bool supports_triangle_fan_ = false;
|
||||||
|
bool supports_extended_range_formats_ = false;
|
||||||
PixelFormat default_color_format_ = PixelFormat::kUnknown;
|
PixelFormat default_color_format_ = PixelFormat::kUnknown;
|
||||||
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
|
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
|
||||||
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
|
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
|
||||||
@ -238,6 +246,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsExtendedRangeFormats(
|
||||||
|
bool value) {
|
||||||
|
supports_extended_range_formats_ = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||||
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
|
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
|
||||||
supports_offscreen_msaa_, //
|
supports_offscreen_msaa_, //
|
||||||
@ -250,6 +264,7 @@ std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
|||||||
supports_decal_sampler_address_mode_, //
|
supports_decal_sampler_address_mode_, //
|
||||||
supports_device_transient_textures_, //
|
supports_device_transient_textures_, //
|
||||||
supports_triangle_fan_, //
|
supports_triangle_fan_, //
|
||||||
|
supports_extended_range_formats_, //
|
||||||
default_color_format_.value_or(PixelFormat::kUnknown), //
|
default_color_format_.value_or(PixelFormat::kUnknown), //
|
||||||
default_stencil_format_.value_or(PixelFormat::kUnknown), //
|
default_stencil_format_.value_or(PixelFormat::kUnknown), //
|
||||||
default_depth_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.
|
/// Note that this may be smaller than the maximum allocatable texture size.
|
||||||
virtual ISize GetMaximumRenderPassAttachmentSize() const = 0;
|
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:
|
protected:
|
||||||
Capabilities();
|
Capabilities();
|
||||||
|
|
||||||
@ -154,6 +161,8 @@ class CapabilitiesBuilder {
|
|||||||
|
|
||||||
CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value);
|
CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value);
|
||||||
|
|
||||||
|
CapabilitiesBuilder& SetSupportsExtendedRangeFormats(bool value);
|
||||||
|
|
||||||
CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value);
|
CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value);
|
||||||
|
|
||||||
CapabilitiesBuilder& SetSupportsTriangleFan(bool value);
|
CapabilitiesBuilder& SetSupportsTriangleFan(bool value);
|
||||||
@ -173,6 +182,7 @@ class CapabilitiesBuilder {
|
|||||||
bool supports_decal_sampler_address_mode_ = false;
|
bool supports_decal_sampler_address_mode_ = false;
|
||||||
bool supports_device_transient_textures_ = false;
|
bool supports_device_transient_textures_ = false;
|
||||||
bool supports_triangle_fan_ = false;
|
bool supports_triangle_fan_ = false;
|
||||||
|
bool supports_extended_range_formats_ = false;
|
||||||
std::optional<PixelFormat> default_color_format_ = std::nullopt;
|
std::optional<PixelFormat> default_color_format_ = std::nullopt;
|
||||||
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
|
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
|
||||||
std::optional<PixelFormat> default_depth_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(SupportsDecalSamplerAddressMode, false);
|
||||||
CAPABILITY_TEST(SupportsDeviceTransientTextures, false);
|
CAPABILITY_TEST(SupportsDeviceTransientTextures, false);
|
||||||
CAPABILITY_TEST(SupportsTriangleFan, false);
|
CAPABILITY_TEST(SupportsTriangleFan, false);
|
||||||
|
CAPABILITY_TEST(SupportsExtendedRangeFormats, false);
|
||||||
|
|
||||||
TEST(CapabilitiesTest, DefaultColorFormat) {
|
TEST(CapabilitiesTest, DefaultColorFormat) {
|
||||||
auto defaults = CapabilitiesBuilder().Build();
|
auto defaults = CapabilitiesBuilder().Build();
|
||||||
|
@ -223,6 +223,7 @@ class MockCapabilities : public Capabilities {
|
|||||||
MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override));
|
MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override));
|
||||||
MOCK_METHOD(bool, SupportsTriangleFan, (), (const override));
|
MOCK_METHOD(bool, SupportsTriangleFan, (), (const override));
|
||||||
MOCK_METHOD(bool, SupportsPrimitiveRestart, (), (const override));
|
MOCK_METHOD(bool, SupportsPrimitiveRestart, (), (const override));
|
||||||
|
MOCK_METHOD(bool, SupportsExtendedRangeFormats, (), (const override));
|
||||||
MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override));
|
MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override));
|
||||||
MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override));
|
MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override));
|
||||||
MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override));
|
MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override));
|
||||||
|
@ -80,10 +80,10 @@ ImageDecoderImpeller::ImageDecoderImpeller(
|
|||||||
const TaskRunners& runners,
|
const TaskRunners& runners,
|
||||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||||
const fml::WeakPtr<IOManager>& io_manager,
|
const fml::WeakPtr<IOManager>& io_manager,
|
||||||
bool supports_wide_gamut,
|
bool wide_gamut_enabled,
|
||||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
||||||
: ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
|
: 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) {
|
gpu_disabled_switch_(gpu_disabled_switch) {
|
||||||
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
||||||
context_ = context_promise.get_future();
|
context_ = context_promise.get_future();
|
||||||
@ -526,7 +526,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
|||||||
target_size = SkISize::Make(target_width, target_height), //
|
target_size = SkISize::Make(target_width, target_height), //
|
||||||
io_runner = runners_.GetIOTaskRunner(), //
|
io_runner = runners_.GetIOTaskRunner(), //
|
||||||
result,
|
result,
|
||||||
supports_wide_gamut = supports_wide_gamut_, //
|
wide_gamut_enabled = wide_gamut_enabled_, //
|
||||||
gpu_disabled_switch = gpu_disabled_switch_]() {
|
gpu_disabled_switch = gpu_disabled_switch_]() {
|
||||||
#if FML_OS_IOS_SIMULATOR
|
#if FML_OS_IOS_SIMULATOR
|
||||||
// No-op backend.
|
// No-op backend.
|
||||||
@ -545,7 +545,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
|||||||
// Always decompress on the concurrent runner.
|
// Always decompress on the concurrent runner.
|
||||||
auto bitmap_result = DecompressTexture(
|
auto bitmap_result = DecompressTexture(
|
||||||
raw_descriptor, target_size, max_size_supported,
|
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());
|
context->GetCapabilities(), context->GetResourceAllocator());
|
||||||
if (!bitmap_result.device_buffer) {
|
if (!bitmap_result.device_buffer) {
|
||||||
result(nullptr, bitmap_result.decode_error);
|
result(nullptr, bitmap_result.decode_error);
|
||||||
|
@ -101,7 +101,10 @@ class ImageDecoderImpeller final : public ImageDecoder {
|
|||||||
private:
|
private:
|
||||||
using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
|
using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
|
||||||
FutureContext 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_;
|
std::shared_ptr<fml::SyncSwitch> gpu_disabled_switch_;
|
||||||
|
|
||||||
/// Only call this method if the GPU is available.
|
/// Only call this method if the GPU is available.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user