mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] use native decal on metal and Vulkan backend (flutter/engine#40723)
[Impeller] use native decal on metal and Vulkan backend
This commit is contained in:
parent
0407296be4
commit
c44b7c1192
@ -306,6 +306,10 @@ enum class SamplerAddressMode {
|
||||
// More modes are almost always supported but they are usually behind
|
||||
// extensions checks. The ones current in these structs are safe (always
|
||||
// supported) defaults.
|
||||
|
||||
/// @brief decal sampling mode is only supported on devices that pass
|
||||
/// the Capabilities.SupportsDecalTileMode check.
|
||||
kDecal,
|
||||
};
|
||||
|
||||
enum class ColorWriteMask : uint64_t {
|
||||
|
||||
@ -214,6 +214,12 @@ std::optional<Entity> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
auto source_descriptor = source_snapshot->sampler_descriptor;
|
||||
switch (tile_mode_) {
|
||||
case Entity::TileMode::kDecal:
|
||||
if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) {
|
||||
input_descriptor.width_address_mode = SamplerAddressMode::kDecal;
|
||||
input_descriptor.height_address_mode = SamplerAddressMode::kDecal;
|
||||
source_descriptor.width_address_mode = SamplerAddressMode::kDecal;
|
||||
source_descriptor.height_address_mode = SamplerAddressMode::kDecal;
|
||||
}
|
||||
break;
|
||||
case Entity::TileMode::kClamp:
|
||||
input_descriptor.width_address_mode = SamplerAddressMode::kClampToEdge;
|
||||
@ -237,7 +243,9 @@ std::optional<Entity> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
}
|
||||
|
||||
bool has_alpha_mask = blur_style_ != BlurStyle::kNormal;
|
||||
bool has_decal_specialization = tile_mode_ == Entity::TileMode::kDecal;
|
||||
bool has_decal_specialization =
|
||||
tile_mode_ == Entity::TileMode::kDecal &&
|
||||
!renderer.GetDeviceCapabilities().SupportsDecalTileMode();
|
||||
|
||||
if (has_alpha_mask && has_decal_specialization) {
|
||||
cmd.pipeline = renderer.GetGaussianBlurAlphaDecalPipeline(options);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "impeller/entity/contents/clip_contents.h"
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/entity/geometry.h"
|
||||
#include "impeller/entity/texture_fill.frag.h"
|
||||
#include "impeller/entity/tiled_texture_fill.frag.h"
|
||||
#include "impeller/entity/tiled_texture_fill.vert.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
@ -16,7 +17,8 @@
|
||||
namespace impeller {
|
||||
|
||||
static std::optional<SamplerAddressMode> TileModeToAddressMode(
|
||||
Entity::TileMode tile_mode) {
|
||||
Entity::TileMode tile_mode,
|
||||
const Capabilities& capabilities) {
|
||||
switch (tile_mode) {
|
||||
case Entity::TileMode::kClamp:
|
||||
return SamplerAddressMode::kClampToEdge;
|
||||
@ -28,6 +30,9 @@ static std::optional<SamplerAddressMode> TileModeToAddressMode(
|
||||
return SamplerAddressMode::kRepeat;
|
||||
break;
|
||||
case Entity::TileMode::kDecal:
|
||||
if (capabilities.SupportsDecalTileMode()) {
|
||||
return SamplerAddressMode::kDecal;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
@ -67,10 +72,11 @@ TiledTextureContents::CreateFilterTexture(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SamplerDescriptor TiledTextureContents::CreateDescriptor() const {
|
||||
SamplerDescriptor TiledTextureContents::CreateDescriptor(
|
||||
const Capabilities& capabilities) const {
|
||||
SamplerDescriptor descriptor = sampler_descriptor_;
|
||||
auto width_mode = TileModeToAddressMode(x_tile_mode_);
|
||||
auto height_mode = TileModeToAddressMode(y_tile_mode_);
|
||||
auto width_mode = TileModeToAddressMode(x_tile_mode_, capabilities);
|
||||
auto height_mode = TileModeToAddressMode(y_tile_mode_, capabilities);
|
||||
if (width_mode.has_value()) {
|
||||
descriptor.width_address_mode = width_mode.value();
|
||||
}
|
||||
@ -80,6 +86,12 @@ SamplerDescriptor TiledTextureContents::CreateDescriptor() const {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
bool TiledTextureContents::UsesEmulatedTileMode(
|
||||
const Capabilities& capabilities) const {
|
||||
return TileModeToAddressMode(x_tile_mode_, capabilities).has_value() &&
|
||||
TileModeToAddressMode(y_tile_mode_, capabilities).has_value();
|
||||
}
|
||||
|
||||
bool TiledTextureContents::Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
RenderPass& pass) const {
|
||||
@ -101,16 +113,13 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
|
||||
auto geometry_result = GetGeometry()->GetPositionUVBuffer(
|
||||
Rect(bounds_origin, Size(texture_size)), GetInverseMatrix(), renderer,
|
||||
entity, pass);
|
||||
bool uses_emulated_tile_mode =
|
||||
UsesEmulatedTileMode(renderer.GetDeviceCapabilities());
|
||||
|
||||
VS::FrameInfo frame_info;
|
||||
frame_info.mvp = geometry_result.transform;
|
||||
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
|
||||
|
||||
FS::FragInfo frag_info;
|
||||
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
|
||||
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
|
||||
frag_info.alpha = GetOpacity();
|
||||
|
||||
Command cmd;
|
||||
cmd.label = "TiledTextureFill";
|
||||
cmd.stencil_reference = entity.GetStencilDepth();
|
||||
@ -121,11 +130,25 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
|
||||
options.stencil_operation = StencilOperation::kIncrementClamp;
|
||||
}
|
||||
options.primitive_type = geometry_result.type;
|
||||
cmd.pipeline = renderer.GetTiledTexturePipeline(options);
|
||||
cmd.pipeline = uses_emulated_tile_mode
|
||||
? renderer.GetTiledTexturePipeline(options)
|
||||
: renderer.GetTexturePipeline(options);
|
||||
|
||||
cmd.BindVertices(geometry_result.vertex_buffer);
|
||||
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
|
||||
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
|
||||
|
||||
if (uses_emulated_tile_mode) {
|
||||
FS::FragInfo frag_info;
|
||||
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
|
||||
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
|
||||
frag_info.alpha = GetOpacity();
|
||||
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
|
||||
} else {
|
||||
TextureFillFragmentShader::FragInfo frag_info;
|
||||
frag_info.alpha = GetOpacity();
|
||||
TextureFillFragmentShader::BindFragInfo(
|
||||
cmd, host_buffer.EmplaceUniform(frag_info));
|
||||
}
|
||||
|
||||
if (color_filter_.has_value()) {
|
||||
auto filtered_texture = CreateFilterTexture(renderer);
|
||||
@ -135,12 +158,12 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
|
||||
FS::BindTextureSampler(
|
||||
cmd, filtered_texture.value(),
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
CreateDescriptor()));
|
||||
CreateDescriptor(renderer.GetDeviceCapabilities())));
|
||||
} else {
|
||||
FS::BindTextureSampler(
|
||||
cmd, texture_,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
CreateDescriptor()));
|
||||
CreateDescriptor(renderer.GetDeviceCapabilities())));
|
||||
}
|
||||
|
||||
if (!pass.AddCommand(std::move(cmd))) {
|
||||
|
||||
@ -53,7 +53,9 @@ class TiledTextureContents final : public ColorSourceContents {
|
||||
std::optional<std::shared_ptr<Texture>> CreateFilterTexture(
|
||||
const ContentContext& renderer) const;
|
||||
|
||||
SamplerDescriptor CreateDescriptor() const;
|
||||
SamplerDescriptor CreateDescriptor(const Capabilities& capabilities) const;
|
||||
|
||||
bool UsesEmulatedTileMode(const Capabilities& capabilities) const;
|
||||
|
||||
std::shared_ptr<Texture> texture_;
|
||||
SamplerDescriptor sampler_descriptor_ = {};
|
||||
|
||||
@ -61,6 +61,8 @@ static GLint ToAddressMode(SamplerAddressMode mode) {
|
||||
return GL_REPEAT;
|
||||
case SamplerAddressMode::kMirror:
|
||||
return GL_MIRRORED_REPEAT;
|
||||
case SamplerAddressMode::kDecal:
|
||||
break; // Unsupported.
|
||||
}
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
@ -53,6 +53,7 @@ static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
.SetSupportsOffscreenMSAA(true)
|
||||
.SetSupportsSSBO(true)
|
||||
.SetSupportsTextureToTextureBlits(true)
|
||||
.SetSupportsDecalTileMode(true)
|
||||
.SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device))
|
||||
.SetDefaultColorFormat(color_format)
|
||||
.SetDefaultStencilFormat(PixelFormat::kS8UInt)
|
||||
|
||||
@ -349,6 +349,8 @@ constexpr MTLSamplerAddressMode ToMTLSamplerAddressMode(
|
||||
return MTLSamplerAddressModeRepeat;
|
||||
case SamplerAddressMode::kMirror:
|
||||
return MTLSamplerAddressModeMirrorRepeat;
|
||||
case SamplerAddressMode::kDecal:
|
||||
return MTLSamplerAddressModeClampToZero;
|
||||
}
|
||||
return MTLSamplerAddressModeClampToEdge;
|
||||
}
|
||||
|
||||
@ -338,6 +338,10 @@ bool CapabilitiesVK::SupportsReadFromResolve() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CapabilitiesVK::SupportsDecalTileMode() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
PixelFormat CapabilitiesVK::GetDefaultColorFormat() const {
|
||||
return color_format_;
|
||||
|
||||
@ -70,6 +70,9 @@ class CapabilitiesVK final : public Capabilities,
|
||||
// |Capabilities|
|
||||
bool SupportsReadFromResolve() const override;
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsDecalTileMode() const override;
|
||||
|
||||
// |Capabilities|
|
||||
PixelFormat GetDefaultColorFormat() const override;
|
||||
|
||||
|
||||
@ -240,6 +240,8 @@ constexpr vk::SamplerAddressMode ToVKSamplerAddressMode(
|
||||
return vk::SamplerAddressMode::eMirroredRepeat;
|
||||
case SamplerAddressMode::kClampToEdge:
|
||||
return vk::SamplerAddressMode::eClampToEdge;
|
||||
case SamplerAddressMode::kDecal:
|
||||
return vk::SamplerAddressMode::eClampToBorder;
|
||||
}
|
||||
|
||||
FML_UNREACHABLE();
|
||||
|
||||
@ -33,13 +33,15 @@ std::shared_ptr<const Sampler> SamplerLibraryVK::GetSampler(
|
||||
const auto address_mode_v = ToVKSamplerAddressMode(desc.height_address_mode);
|
||||
const auto address_mode_w = ToVKSamplerAddressMode(desc.depth_address_mode);
|
||||
|
||||
const auto sampler_create_info = vk::SamplerCreateInfo()
|
||||
.setMagFilter(mag_filter)
|
||||
.setMinFilter(min_filter)
|
||||
.setAddressModeU(address_mode_u)
|
||||
.setAddressModeV(address_mode_v)
|
||||
.setAddressModeW(address_mode_w)
|
||||
.setMipmapMode(mip_map);
|
||||
const auto sampler_create_info =
|
||||
vk::SamplerCreateInfo()
|
||||
.setMagFilter(mag_filter)
|
||||
.setMinFilter(min_filter)
|
||||
.setAddressModeU(address_mode_u)
|
||||
.setAddressModeV(address_mode_v)
|
||||
.setAddressModeW(address_mode_w)
|
||||
.setBorderColor(vk::BorderColor::eFloatTransparentBlack)
|
||||
.setMipmapMode(mip_map);
|
||||
|
||||
auto res = device_.createSamplerUnique(sampler_create_info);
|
||||
if (res.result != vk::Result::eSuccess) {
|
||||
|
||||
@ -51,6 +51,11 @@ class StandardCapabilities final : public Capabilities {
|
||||
return supports_read_from_resolve_;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsDecalTileMode() const override {
|
||||
return supports_decal_tile_mode_;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
PixelFormat GetDefaultColorFormat() const override {
|
||||
return default_color_format_;
|
||||
@ -70,6 +75,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
bool supports_compute,
|
||||
bool supports_compute_subgroups,
|
||||
bool supports_read_from_resolve,
|
||||
bool supports_decal_tile_mode,
|
||||
PixelFormat default_color_format,
|
||||
PixelFormat default_stencil_format)
|
||||
: has_threading_restrictions_(has_threading_restrictions),
|
||||
@ -80,6 +86,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
supports_compute_(supports_compute),
|
||||
supports_compute_subgroups_(supports_compute_subgroups),
|
||||
supports_read_from_resolve_(supports_read_from_resolve),
|
||||
supports_decal_tile_mode_(supports_decal_tile_mode),
|
||||
default_color_format_(default_color_format),
|
||||
default_stencil_format_(default_stencil_format) {}
|
||||
|
||||
@ -93,6 +100,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
bool supports_compute_ = false;
|
||||
bool supports_compute_subgroups_ = false;
|
||||
bool supports_read_from_resolve_ = false;
|
||||
bool supports_decal_tile_mode_ = false;
|
||||
PixelFormat default_color_format_ = PixelFormat::kUnknown;
|
||||
PixelFormat default_stencil_format_ = PixelFormat::kUnknown;
|
||||
|
||||
@ -156,6 +164,11 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultStencilFormat(
|
||||
return *this;
|
||||
}
|
||||
|
||||
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDecalTileMode(bool value) {
|
||||
supports_decal_tile_mode_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
|
||||
has_threading_restrictions_, //
|
||||
@ -166,6 +179,7 @@ std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||
supports_compute_, //
|
||||
supports_compute_subgroups_, //
|
||||
supports_read_from_resolve_, //
|
||||
supports_decal_tile_mode_, //
|
||||
*default_color_format_, //
|
||||
*default_stencil_format_ //
|
||||
));
|
||||
|
||||
@ -31,6 +31,8 @@ class Capabilities {
|
||||
|
||||
virtual bool SupportsReadFromResolve() const = 0;
|
||||
|
||||
virtual bool SupportsDecalTileMode() const = 0;
|
||||
|
||||
virtual PixelFormat GetDefaultColorFormat() const = 0;
|
||||
|
||||
virtual PixelFormat GetDefaultStencilFormat() const = 0;
|
||||
@ -65,6 +67,8 @@ class CapabilitiesBuilder {
|
||||
|
||||
CapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsDecalTileMode(bool value);
|
||||
|
||||
std::unique_ptr<Capabilities> Build();
|
||||
|
||||
private:
|
||||
@ -76,6 +80,7 @@ class CapabilitiesBuilder {
|
||||
bool supports_compute_ = false;
|
||||
bool supports_compute_subgroups_ = false;
|
||||
bool supports_read_from_resolve_ = false;
|
||||
bool supports_decal_tile_mode_ = false;
|
||||
std::optional<PixelFormat> default_color_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user