[Impeller] Document the capabilities. (#45253)
Add docstrings for the capabilities. Include examples/extra detail for the more confusing concepts.
Also renames a couple of capabilities for consistency with format terminology:
* SupportsDecalTileMode -> SupportsDecalSamplerAddressMode
* SupportsMemorylessTextures -> SupportsDeviceTransientTextures
PR is built on https://github.com/flutter/engine/pull/45240 (waiting for tree to reopen).
diff --git a/impeller/core/formats.h b/impeller/core/formats.h
index 6906186..6cc151e 100644
--- a/impeller/core/formats.h
+++ b/impeller/core/formats.h
@@ -383,7 +383,7 @@
// supported) defaults.
/// @brief decal sampling mode is only supported on devices that pass
- /// the Capabilities.SupportsDecalTileMode check.
+ /// the `Capabilities.SupportsDecalSamplerAddressMode` check.
kDecal,
};
diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc
index 7194fd0..1363e16 100644
--- a/impeller/entity/contents/atlas_contents.cc
+++ b/impeller/entity/contents/atlas_contents.cc
@@ -258,7 +258,7 @@
VS::FrameInfo frame_info;
auto dst_sampler_descriptor = sampler_descriptor_;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc
index 663e0a0..3c1b861 100644
--- a/impeller/entity/contents/filters/blend_filter_contents.cc
+++ b/impeller/entity/contents/filters/blend_filter_contents.cc
@@ -176,7 +176,7 @@
typename VS::FrameInfo frame_info;
auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
@@ -195,7 +195,7 @@
FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, dst_sampler);
} else {
auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
@@ -344,7 +344,7 @@
VS::FrameInfo frame_info;
auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
@@ -466,7 +466,7 @@
VS::FrameInfo frame_info;
auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
index d12d8a1..16552f0 100644
--- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
+++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
@@ -230,7 +230,8 @@
auto source_descriptor = source_snapshot->sampler_descriptor;
switch (tile_mode_) {
case Entity::TileMode::kDecal:
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities()
+ .SupportsDecalSamplerAddressMode()) {
input_descriptor.width_address_mode = SamplerAddressMode::kDecal;
input_descriptor.height_address_mode = SamplerAddressMode::kDecal;
source_descriptor.width_address_mode = SamplerAddressMode::kDecal;
@@ -263,7 +264,7 @@
bool has_alpha_mask = blur_style_ != BlurStyle::kNormal;
bool has_decal_specialization =
tile_mode_ == Entity::TileMode::kDecal &&
- !renderer.GetDeviceCapabilities().SupportsDecalTileMode();
+ !renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode();
if (has_alpha_mask && has_decal_specialization) {
cmd.pipeline = renderer.GetGaussianBlurAlphaDecalPipeline(options);
diff --git a/impeller/entity/contents/filters/morphology_filter_contents.cc b/impeller/entity/contents/filters/morphology_filter_contents.cc
index 583ff62..4fd8327 100644
--- a/impeller/entity/contents/filters/morphology_filter_contents.cc
+++ b/impeller/entity/contents/filters/morphology_filter_contents.cc
@@ -123,7 +123,7 @@
cmd.BindVertices(vtx_buffer);
auto sampler_descriptor = input_snapshot->sampler_descriptor;
- if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc
index 0d3bf4d..96b915e 100644
--- a/impeller/entity/contents/framebuffer_blend_contents.cc
+++ b/impeller/entity/contents/framebuffer_blend_contents.cc
@@ -136,7 +136,7 @@
FS::FragInfo frag_info;
auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
- if (!renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
+ if (!renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
// No known devices that support framebuffer fetch but not decal tile mode.
return false;
}
diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc
index bf2bda3..67155fe 100644
--- a/impeller/entity/contents/tiled_texture_contents.cc
+++ b/impeller/entity/contents/tiled_texture_contents.cc
@@ -30,7 +30,7 @@
return SamplerAddressMode::kRepeat;
break;
case Entity::TileMode::kDecal:
- if (capabilities.SupportsDecalTileMode()) {
+ if (capabilities.SupportsDecalSamplerAddressMode()) {
return SamplerAddressMode::kDecal;
}
return std::nullopt;
diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc
index 2fa3ce9..3ab34ac 100644
--- a/impeller/renderer/backend/gles/context_gles.cc
+++ b/impeller/renderer/backend/gles/context_gles.cc
@@ -75,8 +75,8 @@
.SetSupportsComputeSubgroups(false)
.SetSupportsReadFromResolve(false)
.SetSupportsReadFromOnscreenTexture(false)
- .SetSupportsDecalTileMode(false)
- .SetSupportsMemorylessTextures(false)
+ .SetSupportsDecalSamplerAddressMode(false)
+ .SetSupportsDeviceTransientTextures(false)
.Build();
}
diff --git a/impeller/renderer/backend/metal/allocator_mtl.mm b/impeller/renderer/backend/metal/allocator_mtl.mm
index 28c34f7..76e3083 100644
--- a/impeller/renderer/backend/metal/allocator_mtl.mm
+++ b/impeller/renderer/backend/metal/allocator_mtl.mm
@@ -14,7 +14,7 @@
namespace impeller {
-static bool DeviceSupportsMemorylessTargets(id<MTLDevice> device) {
+static bool DeviceSupportsDeviceTransientTargets(id<MTLDevice> device) {
// Refer to the "Memoryless render targets" feature in the table below:
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) {
@@ -95,7 +95,7 @@
return;
}
- supports_memoryless_targets_ = DeviceSupportsMemorylessTargets(device_);
+ supports_memoryless_targets_ = DeviceSupportsDeviceTransientTargets(device_);
supports_uma_ = DeviceHasUnifiedMemoryArchitecture(device_);
max_texture_supported_ = DeviceMaxTextureSizeSupported(device_);
diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm
index 24b3a94..528c185 100644
--- a/impeller/renderer/backend/metal/context_mtl.mm
+++ b/impeller/renderer/backend/metal/context_mtl.mm
@@ -56,7 +56,7 @@
.SetSupportsSSBO(true)
.SetSupportsBufferToTextureBlits(true)
.SetSupportsTextureToTextureBlits(true)
- .SetSupportsDecalTileMode(true)
+ .SetSupportsDecalSamplerAddressMode(true)
.SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device))
.SetDefaultColorFormat(color_format)
.SetDefaultStencilFormat(PixelFormat::kS8UInt)
@@ -65,7 +65,7 @@
.SetSupportsComputeSubgroups(DeviceSupportsComputeSubgroups(device))
.SetSupportsReadFromResolve(true)
.SetSupportsReadFromOnscreenTexture(true)
- .SetSupportsMemorylessTextures(true)
+ .SetSupportsDeviceTransientTextures(true)
.Build();
}
diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc
index 2720a81..93104a1 100644
--- a/impeller/renderer/backend/vulkan/allocator_vk.cc
+++ b/impeller/renderer/backend/vulkan/allocator_vk.cc
@@ -163,7 +163,8 @@
staging_buffer_pool_.reset(CreateBufferPool(allocator));
created_buffer_pool_ &= staging_buffer_pool_.is_valid();
allocator_.reset(allocator);
- supports_memoryless_textures_ = capabilities.SupportsMemorylessTextures();
+ supports_memoryless_textures_ =
+ capabilities.SupportsDeviceTransientTextures();
is_valid_ = true;
}
diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc
index cc5ca77..699fd14 100644
--- a/impeller/renderer/backend/vulkan/capabilities_vk.cc
+++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc
@@ -378,7 +378,7 @@
for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
if (memory_properties.memoryTypes[i].propertyFlags &
vk::MemoryPropertyFlagBits::eLazilyAllocated) {
- supports_memoryless_textures_ = true;
+ supports_device_transient_textures_ = true;
}
}
}
@@ -448,13 +448,13 @@
return false;
}
-bool CapabilitiesVK::SupportsDecalTileMode() const {
+bool CapabilitiesVK::SupportsDecalSamplerAddressMode() const {
return true;
}
// |Capabilities|
-bool CapabilitiesVK::SupportsMemorylessTextures() const {
- return supports_memoryless_textures_;
+bool CapabilitiesVK::SupportsDeviceTransientTextures() const {
+ return supports_device_transient_textures_;
}
// |Capabilities|
diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h
index d6afdbf..2e5db50 100644
--- a/impeller/renderer/backend/vulkan/capabilities_vk.h
+++ b/impeller/renderer/backend/vulkan/capabilities_vk.h
@@ -85,10 +85,10 @@
bool SupportsReadFromOnscreenTexture() const override;
// |Capabilities|
- bool SupportsDecalTileMode() const override;
+ bool SupportsDecalSamplerAddressMode() const override;
// |Capabilities|
- bool SupportsMemorylessTextures() const override;
+ bool SupportsDeviceTransientTextures() const override;
// |Capabilities|
PixelFormat GetDefaultColorFormat() const override;
@@ -108,7 +108,7 @@
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
vk::PhysicalDeviceProperties device_properties_;
bool supports_compute_subgroups_ = false;
- bool supports_memoryless_textures_ = false;
+ bool supports_device_transient_textures_ = false;
bool is_valid_ = false;
bool HasExtension(const std::string& ext) const;
diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc
index 73ac155..928d96f 100644
--- a/impeller/renderer/capabilities.cc
+++ b/impeller/renderer/capabilities.cc
@@ -57,8 +57,8 @@
}
// |Capabilities|
- bool SupportsDecalTileMode() const override {
- return supports_decal_tile_mode_;
+ bool SupportsDecalSamplerAddressMode() const override {
+ return supports_decal_sampler_address_mode_;
}
// |Capabilities|
@@ -76,8 +76,8 @@
return default_depth_stencil_format_;
}
- bool SupportsMemorylessTextures() const override {
- return supports_memoryless_textures_;
+ bool SupportsDeviceTransientTextures() const override {
+ return supports_device_transient_textures_;
}
private:
@@ -90,8 +90,8 @@
bool supports_compute_subgroups,
bool supports_read_from_onscreen_texture,
bool supports_read_from_resolve,
- bool supports_decal_tile_mode,
- bool supports_memoryless_textures,
+ bool supports_decal_sampler_address_mode,
+ bool supports_device_transient_textures,
PixelFormat default_color_format,
PixelFormat default_stencil_format,
PixelFormat default_depth_stencil_format)
@@ -105,8 +105,9 @@
supports_read_from_onscreen_texture_(
supports_read_from_onscreen_texture),
supports_read_from_resolve_(supports_read_from_resolve),
- supports_decal_tile_mode_(supports_decal_tile_mode),
- supports_memoryless_textures_(supports_memoryless_textures),
+ supports_decal_sampler_address_mode_(
+ supports_decal_sampler_address_mode),
+ supports_device_transient_textures_(supports_device_transient_textures),
default_color_format_(default_color_format),
default_stencil_format_(default_stencil_format),
default_depth_stencil_format_(default_depth_stencil_format) {}
@@ -122,8 +123,8 @@
bool supports_compute_subgroups_ = false;
bool supports_read_from_onscreen_texture_ = false;
bool supports_read_from_resolve_ = false;
- bool supports_decal_tile_mode_ = false;
- bool supports_memoryless_textures_ = false;
+ bool supports_decal_sampler_address_mode_ = false;
+ bool supports_device_transient_textures_ = false;
PixelFormat default_color_format_ = PixelFormat::kUnknown;
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown;
@@ -204,14 +205,15 @@
return *this;
}
-CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDecalTileMode(bool value) {
- supports_decal_tile_mode_ = value;
+CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDecalSamplerAddressMode(
+ bool value) {
+ supports_decal_sampler_address_mode_ = value;
return *this;
}
-CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsMemorylessTextures(
+CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDeviceTransientTextures(
bool value) {
- supports_memoryless_textures_ = value;
+ supports_device_transient_textures_ = value;
return *this;
}
@@ -226,8 +228,8 @@
supports_compute_subgroups_, //
supports_read_from_onscreen_texture_, //
supports_read_from_resolve_, //
- supports_decal_tile_mode_, //
- supports_memoryless_textures_, //
+ supports_decal_sampler_address_mode_, //
+ supports_device_transient_textures_, //
default_color_format_.value_or(PixelFormat::kUnknown), //
default_stencil_format_.value_or(PixelFormat::kUnknown), //
default_depth_stencil_format_.value_or(PixelFormat::kUnknown) //
diff --git a/impeller/renderer/capabilities.h b/impeller/renderer/capabilities.h
index 50f3eb8..21085ae 100644
--- a/impeller/renderer/capabilities.h
+++ b/impeller/renderer/capabilities.h
@@ -15,32 +15,92 @@
public:
virtual ~Capabilities();
+ /// @brief Whether the context backend supports attaching offscreen MSAA
+ /// color/stencil textures.
virtual bool SupportsOffscreenMSAA() const = 0;
+ /// @brief Whether the context backend supports binding Shader Storage Buffer
+ /// Objects (SSBOs) to pipelines.
virtual bool SupportsSSBO() const = 0;
+ /// @brief Whether the context backend supports blitting from a given
+ /// `DeviceBuffer` view to a texture region (via the relevant
+ /// `BlitPass::AddCopy` overloads).
virtual bool SupportsBufferToTextureBlits() const = 0;
+ /// @brief Whether the context backend supports blitting from one texture
+ /// region to another texture region (via the relevant
+ /// `BlitPass::AddCopy` overloads).
virtual bool SupportsTextureToTextureBlits() const = 0;
+ /// @brief Whether the context backend is able to support pipelines with
+ /// shaders that read from the framebuffer (i.e. pixels that have been
+ /// written by previous draw calls in the current render pass).
+ ///
+ /// Example of reading from the first color attachment in a GLSL
+ /// shader:
+ /// ```
+ /// uniform subpassInput subpass_input;
+ ///
+ /// out vec4 frag_color;
+ ///
+ /// void main() {
+ /// vec4 color = subpassLoad(subpass_input);
+ /// // Invert the colors drawn to the framebuffer.
+ /// frag_color = vec4(vec3(1) - color.rgb, color.a);
+ /// }
+ /// ```
virtual bool SupportsFramebufferFetch() const = 0;
+ /// @brief Whether the context backend supports `ComputePass`.
virtual bool SupportsCompute() const = 0;
+ /// @brief Whether the context backend supports configuring `ComputePass`
+ /// command subgroups.
virtual bool SupportsComputeSubgroups() const = 0;
+ /// @brief Whether the context backend supports binding the on-screen surface
+ /// texture for shader reading.
virtual bool SupportsReadFromOnscreenTexture() const = 0;
+ /// @brief Whether the context backend supports binding the current
+ /// `RenderPass` attachments. This is supported if the backend can
+ /// guarantee that attachment textures will not be mutated until the
+ /// render pass has fully completed.
+ ///
+ /// This is possible because many mobile graphics cards track
+ /// `RenderPass` attachment state in intermediary tile memory prior to
+ /// Storing the pass in the heap allocated attachments on DRAM.
+ /// Metal's hazard tracking and Vulkan's barriers are granular enough
+ /// to allow for safely accessing attachment textures prior to storage
+ /// in the same `RenderPass`.
virtual bool SupportsReadFromResolve() const = 0;
- virtual bool SupportsDecalTileMode() const = 0;
+ /// @brief Whether the context backend supports `SamplerAddressMode::Decal`.
+ virtual bool SupportsDecalSamplerAddressMode() const = 0;
- virtual bool SupportsMemorylessTextures() const = 0;
+ /// @brief Whether the context backend supports allocating
+ /// `StorageMode::kDeviceTransient` (aka "memoryless") textures, which
+ /// are temporary textures kept in tile memory for the duration of the
+ /// `RenderPass` it's attached to.
+ ///
+ /// This feature is especially useful for MSAA and stencils.
+ virtual bool SupportsDeviceTransientTextures() const = 0;
+ /// @brief Returns a supported `PixelFormat` for textures that store
+ /// 4-channel colors (red/green/blue/alpha).
virtual PixelFormat GetDefaultColorFormat() const = 0;
+ /// @brief Returns a supported `PixelFormat` for textures that store stencil
+ /// information. May include a depth channel if a stencil-only format
+ /// is not available.
virtual PixelFormat GetDefaultStencilFormat() const = 0;
+ /// @brief Returns a supported `PixelFormat` for textures that store both a
+ /// stencil and depth component. This will never return a depth-only
+ /// or stencil-only texture.
+ /// Returns `PixelFormat::kUnknown` if no suitable depth+stencil
+ /// format was found.
virtual PixelFormat GetDefaultDepthStencilFormat() const = 0;
protected:
@@ -79,9 +139,9 @@
CapabilitiesBuilder& SetDefaultDepthStencilFormat(PixelFormat value);
- CapabilitiesBuilder& SetSupportsDecalTileMode(bool value);
+ CapabilitiesBuilder& SetSupportsDecalSamplerAddressMode(bool value);
- CapabilitiesBuilder& SetSupportsMemorylessTextures(bool value);
+ CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value);
std::unique_ptr<Capabilities> Build();
@@ -95,8 +155,8 @@
bool supports_compute_subgroups_ = false;
bool supports_read_from_onscreen_texture_ = false;
bool supports_read_from_resolve_ = false;
- bool supports_decal_tile_mode_ = false;
- bool supports_memoryless_textures_ = false;
+ bool supports_decal_sampler_address_mode_ = false;
+ bool supports_device_transient_textures_ = 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;
diff --git a/impeller/renderer/capabilities_unittests.cc b/impeller/renderer/capabilities_unittests.cc
index 2fd9eca..beab9a9 100644
--- a/impeller/renderer/capabilities_unittests.cc
+++ b/impeller/renderer/capabilities_unittests.cc
@@ -27,8 +27,8 @@
CAPABILITY_TEST(SupportsComputeSubgroups, false);
CAPABILITY_TEST(SupportsReadFromOnscreenTexture, false);
CAPABILITY_TEST(SupportsReadFromResolve, false);
-CAPABILITY_TEST(SupportsDecalTileMode, false);
-CAPABILITY_TEST(SupportsMemorylessTextures, false);
+CAPABILITY_TEST(SupportsDecalSamplerAddressMode, false);
+CAPABILITY_TEST(SupportsDeviceTransientTextures, false);
TEST(CapabilitiesTest, DefaultColorFormat) {
auto defaults = CapabilitiesBuilder().Build();