diff --git a/impeller/core/formats.h b/impeller/core/formats.h index 69061860edfa3..6cc151e81939c 100644 --- a/impeller/core/formats.h +++ b/impeller/core/formats.h @@ -383,7 +383,7 @@ enum class SamplerAddressMode { // 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 7194fd0231b45..1363e169faea7 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -258,7 +258,7 @@ bool AtlasContents::Render(const ContentContext& renderer, 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 663e0a048bef8..3c1b8617612f2 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -176,7 +176,7 @@ static std::optional AdvancedBlend( 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 @@ static std::optional AdvancedBlend( 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 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( 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 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( 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 d12d8a13d8597..16552f0f8fdc3 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 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( 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 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( 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 583ff625e11b7..4fd83270c3df8 100644 --- a/impeller/entity/contents/filters/morphology_filter_contents.cc +++ b/impeller/entity/contents/filters/morphology_filter_contents.cc @@ -123,7 +123,7 @@ std::optional DirectionalMorphologyFilterContents::RenderFilter( 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 0d3bf4da23c9d..96b915ee4ac23 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -136,7 +136,7 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, 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 bf2bda327ba17..67155fe2b9450 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -30,7 +30,7 @@ static std::optional TileModeToAddressMode( 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 2fa3ce9e0f1ab..3ab34acc40bd9 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -75,8 +75,8 @@ ContextGLES::ContextGLES(std::unique_ptr gl, .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 28c34f7c69811..76e3083b7fbcd 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 device) { +static bool DeviceSupportsDeviceTransientTargets(id 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 @@ static bool SupportsLossyTextureCompression(id device) { 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 24b3a94b904e7..528c1854802a3 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -56,7 +56,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { .SetSupportsSSBO(true) .SetSupportsBufferToTextureBlits(true) .SetSupportsTextureToTextureBlits(true) - .SetSupportsDecalTileMode(true) + .SetSupportsDecalSamplerAddressMode(true) .SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device)) .SetDefaultColorFormat(color_format) .SetDefaultStencilFormat(PixelFormat::kS8UInt) @@ -65,7 +65,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { .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 2720a81587060..93104a1c91944 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -163,7 +163,8 @@ AllocatorVK::AllocatorVK(std::weak_ptr context, 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 cc5ca77f6e5ea..699fd14d3e146 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -378,7 +378,7 @@ bool CapabilitiesVK::SetPhysicalDevice(const vk::PhysicalDevice& device) { 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 @@ bool CapabilitiesVK::SupportsReadFromOnscreenTexture() const { 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 d6afdbfc37920..2e5db50c01cb3 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -85,10 +85,10 @@ class CapabilitiesVK final : public Capabilities, 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 @@ class CapabilitiesVK final : public Capabilities, 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 73ac155175c18..928d96f73865d 100644 --- a/impeller/renderer/capabilities.cc +++ b/impeller/renderer/capabilities.cc @@ -57,8 +57,8 @@ class StandardCapabilities final : public Capabilities { } // |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 @@ class StandardCapabilities final : public Capabilities { 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 @@ class StandardCapabilities final : public Capabilities { 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 @@ class StandardCapabilities final : public Capabilities { 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 @@ class StandardCapabilities final : public Capabilities { 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 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultDepthStencilFormat( 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 @@ std::unique_ptr CapabilitiesBuilder::Build() { 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 50f3eb8ac41aa..21085ae41994f 100644 --- a/impeller/renderer/capabilities.h +++ b/impeller/renderer/capabilities.h @@ -15,32 +15,92 @@ class Capabilities { 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 @@ class CapabilitiesBuilder { CapabilitiesBuilder& SetDefaultDepthStencilFormat(PixelFormat value); - CapabilitiesBuilder& SetSupportsDecalTileMode(bool value); + CapabilitiesBuilder& SetSupportsDecalSamplerAddressMode(bool value); - CapabilitiesBuilder& SetSupportsMemorylessTextures(bool value); + CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value); std::unique_ptr Build(); @@ -95,8 +155,8 @@ class CapabilitiesBuilder { 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 default_color_format_ = std::nullopt; std::optional default_stencil_format_ = std::nullopt; std::optional default_depth_stencil_format_ = std::nullopt; diff --git a/impeller/renderer/capabilities_unittests.cc b/impeller/renderer/capabilities_unittests.cc index 2fd9eca70aa32..beab9a9a53615 100644 --- a/impeller/renderer/capabilities_unittests.cc +++ b/impeller/renderer/capabilities_unittests.cc @@ -27,8 +27,8 @@ CAPABILITY_TEST(SupportsCompute, false); 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();