From 1283387b56f166ba2cb1f372f38d67680e0a29db Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 16 Sep 2024 12:14:48 -0700 Subject: [PATCH 1/2] [Impeller] add triangle fan support and remove drawVertices copying. --- impeller/core/formats.h | 14 +- .../display_list/aiks_dl_blur_unittests.cc | 1 + impeller/display_list/dl_dispatcher.cc | 14 +- impeller/display_list/dl_dispatcher.h | 8 +- impeller/display_list/dl_vertices_geometry.cc | 235 +++++++++++++++--- impeller/display_list/dl_vertices_geometry.h | 47 +++- impeller/entity/geometry/vertices_geometry.cc | 196 --------------- impeller/entity/geometry/vertices_geometry.h | 55 +--- .../backend/gles/capabilities_gles.cc | 4 + .../renderer/backend/gles/capabilities_gles.h | 3 + impeller/renderer/backend/gles/formats_gles.h | 2 + .../renderer/backend/metal/context_mtl.mm | 1 + impeller/renderer/backend/metal/formats_mtl.h | 3 + .../backend/vulkan/capabilities_vk.cc | 4 + .../renderer/backend/vulkan/capabilities_vk.h | 3 + impeller/renderer/backend/vulkan/formats_vk.h | 2 + impeller/renderer/capabilities.cc | 12 + impeller/renderer/capabilities.h | 6 + impeller/renderer/capabilities_unittests.cc | 1 + impeller/renderer/testing/mocks.h | 1 + 20 files changed, 320 insertions(+), 292 deletions(-) diff --git a/impeller/core/formats.h b/impeller/core/formats.h index 5b0751454b0bf..575c5431f0430 100644 --- a/impeller/core/formats.h +++ b/impeller/core/formats.h @@ -350,13 +350,13 @@ enum class IndexType { /// Decides how backend draws pixels based on input vertices. enum class PrimitiveType : uint8_t { - /// Draws a triage for each separate set of three vertices. + /// Draws a triangle for each separate set of three vertices. /// /// Vertices [A, B, C, D, E, F] will produce triages /// [ABC, DEF]. kTriangle, - /// Draws a triage for every adjacent three vertices. + /// Draws a triangle for every adjacent three vertices. /// /// Vertices [A, B, C, D, E, F] will produce triages /// [ABC, BCD, CDE, DEF]. @@ -376,8 +376,14 @@ enum class PrimitiveType : uint8_t { /// Draws a point at each input vertex. kPoint, - // Triangle fans are implementation dependent and need extra extensions - // checks. Hence, they are not supported here. + + /// Draws a triangle for every two vertices, after the first. + /// + /// The first vertex acts as the hub, all following vertices connect with + /// this hub to "fan" out from the first vertex. + /// + /// Triangle fans are not supported in Metal and need a capability check. + kTriangleFan, }; enum class PolygonMode { diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index a8bffae708a9f..46aa3b7dc33fe 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -1076,6 +1076,7 @@ TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) { FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTextureToTextureBlits); FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan); ASSERT_TRUE(SetCapabilities(mock_capabilities).ok()); auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")); diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 7788ae3a593e8..d58a6339aafac 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -1076,14 +1076,19 @@ void DlDispatcherBase::drawPoints(PointMode mode, } } -// |flutter::DlOpReceiver| void DlDispatcherBase::drawVertices( + const std::shared_ptr& vertices, + flutter::DlBlendMode dl_mode) {} + +// |flutter::DlOpReceiver| +void ExperimentalDlDispatcher::drawVertices( const std::shared_ptr& vertices, flutter::DlBlendMode dl_mode) { AUTO_DEPTH_WATCHER(1u); - GetCanvas().DrawVertices(MakeVertices(vertices), ToBlendMode(dl_mode), - paint_); + GetCanvas().DrawVertices( + std::make_shared(vertices, renderer_), + ToBlendMode(dl_mode), paint_); } // |flutter::DlOpReceiver| @@ -1349,7 +1354,8 @@ ExperimentalDlDispatcher::ExperimentalDlDispatcher( bool has_root_backdrop_filter, flutter::DlBlendMode max_root_blend_mode, IRect cull_rect) - : canvas_(renderer, + : renderer_(renderer), + canvas_(renderer, render_target, has_root_backdrop_filter || RequiresReadbackForBlends(renderer, max_root_blend_mode), diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h index 4bda27218b9a9..55694fd61aa1f 100644 --- a/impeller/display_list/dl_dispatcher.h +++ b/impeller/display_list/dl_dispatcher.h @@ -14,7 +14,6 @@ #include "impeller/aiks/experimental_canvas.h" #include "impeller/aiks/paint.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/geometry/color.h" namespace impeller { @@ -236,7 +235,7 @@ class DlDispatcherBase : public flutter::DlOpReceiver { virtual Canvas& GetCanvas() = 0; - private: + protected: Paint paint_; Matrix initial_matrix_; @@ -314,7 +313,12 @@ class ExperimentalDlDispatcher : public DlDispatcherBase { void FinishRecording() { canvas_.EndReplay(); } + // |flutter::DlOpReceiver| + void drawVertices(const std::shared_ptr& vertices, + flutter::DlBlendMode dl_mode) override; + private: + const ContentContext& renderer_; ExperimentalCanvas canvas_; Canvas& GetCanvas() override; diff --git a/impeller/display_list/dl_vertices_geometry.cc b/impeller/display_list/dl_vertices_geometry.cc index 6a93757f3decb..80a515c09919d 100644 --- a/impeller/display_list/dl_vertices_geometry.cc +++ b/impeller/display_list/dl_vertices_geometry.cc @@ -5,61 +5,220 @@ #include "impeller/display_list/dl_vertices_geometry.h" #include "display_list/dl_vertices.h" +#include "impeller/core/formats.h" #include "impeller/display_list/skia_conversions.h" -#include "impeller/entity/geometry/vertices_geometry.h" #include "impeller/geometry/point.h" #include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkRect.h" namespace impeller { -static Rect ToRect(const SkRect& rect) { - return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); +namespace { + +// Fan mode isn't natively supported on Metal backends. Unroll into triangle +// mode by manipulating the index array. +// +// In Triangle fan, the first vertex is shared across all triangles, and then +// each sliding window of two vertices plus that first vertex defines a +// triangle. +static std::vector fromFanIndices(size_t vertex_count, + size_t index_count, + const uint16_t* indices) { + std::vector unrolled_indices; + + // Un-fan index buffer if provided. + if (index_count > 0u) { + if (index_count < 3u) { + return {}; + } + + auto center_point = indices[0]; + for (auto i = 1u; i < index_count - 1; i++) { + unrolled_indices.push_back(center_point); + unrolled_indices.push_back(indices[i]); + unrolled_indices.push_back(indices[i + 1]); + } + } else { + if (vertex_count < 3u) { + return {}; + } + + // If indices were not provided, create an index buffer that unfans + // triangles instead of re-writing points, colors, et cetera. + for (auto i = 1u; i < vertex_count - 1; i++) { + unrolled_indices.push_back(0); + unrolled_indices.push_back(i); + unrolled_indices.push_back(i + 1); + } + } + return unrolled_indices; } -static VerticesGeometry::VertexMode ToVertexMode(flutter::DlVertexMode mode) { - switch (mode) { - case flutter::DlVertexMode::kTriangles: - return VerticesGeometry::VertexMode::kTriangles; - case flutter::DlVertexMode::kTriangleStrip: - return VerticesGeometry::VertexMode::kTriangleStrip; +} // namespace + +/////// Vertices Geometry /////// + +DlVerticesGeometry::DlVerticesGeometry( + const std::shared_ptr& vertices, + const ContentContext& renderer) + : vertices_(vertices) { + performed_normalization_ = MaybePerformIndexNormalization(renderer); + bounds_ = skia_conversions::ToRect(vertices_->bounds()); +} + +PrimitiveType DlVerticesGeometry::GetPrimitiveType() const { + switch (vertices_->mode()) { case flutter::DlVertexMode::kTriangleFan: - return VerticesGeometry::VertexMode::kTriangleFan; - }; + // Unrolled into triangle mode. + if (performed_normalization_) { + return PrimitiveType::kTriangle; + } + return PrimitiveType::kTriangleFan; + case flutter::DlVertexMode::kTriangleStrip: + return PrimitiveType::kTriangleStrip; + case flutter::DlVertexMode::kTriangles: + return PrimitiveType::kTriangle; + } +} + +bool DlVerticesGeometry::HasVertexColors() const { + return vertices_->colors() != nullptr; } -std::shared_ptr MakeVertices( - const std::shared_ptr& vertices) { - auto bounds = ToRect(vertices->bounds()); - auto mode = ToVertexMode(vertices->mode()); - std::vector positions(vertices->vertex_count()); - for (auto i = 0; i < vertices->vertex_count(); i++) { - positions[i] = skia_conversions::ToPoint(vertices->vertices()[i]); +bool DlVerticesGeometry::HasTextureCoordinates() const { + return vertices_->texture_coordinates() != nullptr; +} + +std::optional DlVerticesGeometry::GetTextureCoordinateCoverge() const { + if (!HasTextureCoordinates()) { + return std::nullopt; + } + auto vertex_count = vertices_->vertex_count(); + if (vertex_count == 0) { + return std::nullopt; } - std::vector indices(vertices->index_count()); - for (auto i = 0; i < vertices->index_count(); i++) { - indices[i] = vertices->indices()[i]; + auto first = vertices_->texture_coordinates(); + auto left = first->x(); + auto top = first->y(); + auto right = first->x(); + auto bottom = first->y(); + int i = 1; + for (auto it = first + 1; i < vertex_count; ++it, i++) { + left = std::min(left, it->x()); + top = std::min(top, it->y()); + right = std::max(right, it->x()); + bottom = std::max(bottom, it->y()); } + return Rect::MakeLTRB(left, top, right, bottom); +} - std::vector colors; - if (vertices->colors()) { - colors.reserve(vertices->vertex_count()); - for (auto i = 0; i < vertices->vertex_count(); i++) { - colors.push_back( - skia_conversions::ToColor(vertices->colors()[i]).Premultiply()); - } +GeometryResult DlVerticesGeometry::GetPositionBuffer( + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + int vertex_count = vertices_->vertex_count(); + BufferView vertex_buffer = renderer.GetTransientsBuffer().Emplace( + vertices_->vertices(), vertex_count * sizeof(SkPoint), alignof(SkPoint)); + + BufferView index_buffer = {}; + auto index_count = + performed_normalization_ ? indices_.size() : vertices_->index_count(); + const uint16_t* indices_data = + performed_normalization_ ? indices_.data() : vertices_->indices(); + if (index_count) { + index_buffer = renderer.GetTransientsBuffer().Emplace( + indices_data, index_count * sizeof(uint16_t), alignof(uint16_t)); } - std::vector texture_coordinates; - if (vertices->texture_coordinates()) { - texture_coordinates.reserve(vertices->vertex_count()); - for (auto i = 0; i < vertices->vertex_count(); i++) { - texture_coordinates.push_back( - skia_conversions::ToPoint(vertices->texture_coordinates()[i])); - } + + return GeometryResult{ + .type = GetPrimitiveType(), + .vertex_buffer = + { + .vertex_buffer = vertex_buffer, + .index_buffer = index_buffer, + .vertex_count = index_count > 0 ? index_count : vertex_count, + .index_type = + index_count > 0 ? IndexType::k16bit : IndexType::kNone, + }, + .transform = entity.GetShaderTransform(pass), + }; +} + +GeometryResult DlVerticesGeometry::GetPositionUVColorBuffer( + Rect texture_coverage, + Matrix effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = PorterDuffBlendPipeline::VertexShader; + + int vertex_count = vertices_->vertex_count(); + Matrix uv_transform = + texture_coverage.GetNormalizingTransform() * effect_transform; + bool has_texture_coordinates = HasTextureCoordinates(); + bool has_colors = HasVertexColors(); + + const SkPoint* coordinates = has_texture_coordinates + ? vertices_->texture_coordinates() + : vertices_->vertices(); + BufferView vertex_buffer = renderer.GetTransientsBuffer().Emplace( + vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData), + [&](uint8_t* data) { + VS::PerVertexData* vtx_contents = + reinterpret_cast(data); + for (auto i = 0; i < vertex_count; i++) { + Point texture_coord = skia_conversions::ToPoint(coordinates[i]); + Point uv = uv_transform * texture_coord; + Color color = has_colors + ? skia_conversions::ToColor(vertices_->colors()[i]) + .Premultiply() + : Color::BlackTransparent(); + VS::PerVertexData vertex_data = { + .vertices = skia_conversions::ToPoint(vertices_->vertices()[i]), + .texture_coords = uv, + .color = color}; + vtx_contents[i] = vertex_data; + } + }); + + BufferView index_buffer = {}; + auto index_count = + performed_normalization_ ? indices_.size() : vertices_->index_count(); + const uint16_t* indices_data = + performed_normalization_ ? indices_.data() : vertices_->indices(); + if (index_count) { + index_buffer = renderer.GetTransientsBuffer().Emplace( + indices_data, index_count * sizeof(uint16_t), alignof(uint16_t)); + } + + return GeometryResult{ + .type = GetPrimitiveType(), + .vertex_buffer = + { + .vertex_buffer = vertex_buffer, + .index_buffer = index_buffer, + .vertex_count = index_count > 0 ? index_count : vertex_count, + .index_type = + index_count > 0 ? IndexType::k16bit : IndexType::kNone, + }, + .transform = entity.GetShaderTransform(pass), + }; +} + +std::optional DlVerticesGeometry::GetCoverage( + const Matrix& transform) const { + return bounds_.TransformBounds(transform); +} + +bool DlVerticesGeometry::MaybePerformIndexNormalization( + const ContentContext& renderer) { + if (vertices_->mode() == flutter::DlVertexMode::kTriangleFan && + !renderer.GetDeviceCapabilities().SupportsTriangleFan()) { + indices_ = fromFanIndices(vertices_->vertex_count(), + vertices_->index_count(), vertices_->indices()); + return true; } - return std::make_shared( - positions, indices, texture_coordinates, colors, bounds, mode); + return false; } } // namespace impeller diff --git a/impeller/display_list/dl_vertices_geometry.h b/impeller/display_list/dl_vertices_geometry.h index 96790af408083..a985433ae7bf4 100644 --- a/impeller/display_list/dl_vertices_geometry.h +++ b/impeller/display_list/dl_vertices_geometry.h @@ -6,13 +6,54 @@ #define FLUTTER_IMPELLER_DISPLAY_LIST_DL_VERTICES_GEOMETRY_H_ #include "flutter/display_list/dl_vertices.h" - +#include "impeller/core/formats.h" #include "impeller/entity/geometry/vertices_geometry.h" namespace impeller { -std::shared_ptr MakeVertices( - const std::shared_ptr& vertices); +/// @brief A geometry that is created from a DlVertices object. +class DlVerticesGeometry final : public VerticesGeometry { + public: + DlVerticesGeometry(const std::shared_ptr& vertices, + const ContentContext& renderer); + + ~DlVerticesGeometry() = default; + + GeometryResult GetPositionUVColorBuffer(Rect texture_coverage, + Matrix effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + // |Geometry| + GeometryResult GetPositionBuffer(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + // |Geometry| + std::optional GetCoverage(const Matrix& transform) const override; + + bool HasVertexColors() const override; + + bool HasTextureCoordinates() const override; + + std::optional GetTextureCoordinateCoverge() const override; + + private: + PrimitiveType GetPrimitiveType() const; + + /// @brief Check if index normalization is required, returning whether or + /// not it was performed. + /// + /// If true, [indices_] should be used in place of the vertices object's + /// indices. + bool MaybePerformIndexNormalization(const ContentContext& renderer); + + const std::shared_ptr vertices_; + std::vector indices_; + bool performed_normalization_; + Rect bounds_; +}; } // namespace impeller diff --git a/impeller/entity/geometry/vertices_geometry.cc b/impeller/entity/geometry/vertices_geometry.cc index f9e86d41c866d..2d27592853513 100644 --- a/impeller/entity/geometry/vertices_geometry.cc +++ b/impeller/entity/geometry/vertices_geometry.cc @@ -4,204 +4,8 @@ #include "impeller/entity/geometry/vertices_geometry.h" -#include -#include - -#include "impeller/core/buffer_view.h" -#include "impeller/entity/contents/content_context.h" -#include "impeller/geometry/color.h" - namespace impeller { -// Fan mode isn't natively supported. Unroll into triangle mode by -// manipulating the index array. // -// In Triangle fan, the first vertex is shared across all triangles, and then -// each sliding window of two vertices plus that first vertex defines a -// triangle. -static std::vector fromFanIndices( - const std::vector& vertices, - const std::vector& indices) { - std::vector unrolled_indices; - - // Un-fan index buffer if provided. - if (indices.size() > 0u) { - if (indices.size() < 3u) { - return {}; - } - - auto center_point = indices[0]; - for (auto i = 1u; i < indices.size() - 1; i++) { - unrolled_indices.push_back(center_point); - unrolled_indices.push_back(indices[i]); - unrolled_indices.push_back(indices[i + 1]); - } - } else { - if (vertices.size() < 3u) { - return {}; - } - - // If indices were not provided, create an index buffer that unfans - // triangles instead of re-writing points, colors, et cetera. - for (auto i = 1u; i < vertices.size() - 1; i++) { - unrolled_indices.push_back(0); - unrolled_indices.push_back(i); - unrolled_indices.push_back(i + 1); - } - } - return unrolled_indices; -} - -/////// Vertices Geometry /////// - -VerticesGeometry::VerticesGeometry(std::vector vertices, - std::vector indices, - std::vector texture_coordinates, - std::vector colors, - Rect bounds, - VertexMode vertex_mode) - : vertices_(std::move(vertices)), - colors_(std::move(colors)), - texture_coordinates_(std::move(texture_coordinates)), - indices_(std::move(indices)), - bounds_(bounds), - vertex_mode_(vertex_mode) { - NormalizeIndices(); -} - -PrimitiveType VerticesGeometry::GetPrimitiveType() const { - switch (vertex_mode_) { - case VerticesGeometry::VertexMode::kTriangleFan: - // Unrolled into triangle mode. - return PrimitiveType::kTriangle; - case VerticesGeometry::VertexMode::kTriangleStrip: - return PrimitiveType::kTriangleStrip; - case VerticesGeometry::VertexMode::kTriangles: - return PrimitiveType::kTriangle; - } -} - -void VerticesGeometry::NormalizeIndices() { - // Convert triangle fan if present. - if (vertex_mode_ == VerticesGeometry::VertexMode::kTriangleFan) { - indices_ = fromFanIndices(vertices_, indices_); - return; - } -} - -bool VerticesGeometry::HasVertexColors() const { - return colors_.size() > 0; -} - -bool VerticesGeometry::HasTextureCoordinates() const { - return texture_coordinates_.size() > 0; -} - -std::optional VerticesGeometry::GetTextureCoordinateCoverge() const { - if (!HasTextureCoordinates()) { - return std::nullopt; - } - auto vertex_count = vertices_.size(); - if (vertex_count == 0) { - return std::nullopt; - } - - return Rect::MakePointBounds(texture_coordinates_.begin(), - texture_coordinates_.end()); -} - -GeometryResult VerticesGeometry::GetPositionBuffer( - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) const { - auto index_count = indices_.size(); - auto vertex_count = vertices_.size(); - - size_t total_vtx_bytes = vertex_count * sizeof(float) * 2; - size_t total_idx_bytes = index_count * sizeof(uint16_t); - - auto vertex_buffer = renderer.GetTransientsBuffer().Emplace( - reinterpret_cast(vertices_.data()), total_vtx_bytes, - alignof(float)); - - BufferView index_buffer = {}; - if (index_count) { - index_buffer = renderer.GetTransientsBuffer().Emplace( - indices_.data(), total_idx_bytes, alignof(uint16_t)); - } - - return GeometryResult{ - .type = GetPrimitiveType(), - .vertex_buffer = - { - .vertex_buffer = vertex_buffer, - .index_buffer = index_buffer, - .vertex_count = index_count > 0 ? index_count : vertex_count, - .index_type = - index_count > 0 ? IndexType::k16bit : IndexType::kNone, - }, - .transform = entity.GetShaderTransform(pass), - }; -} - -GeometryResult VerticesGeometry::GetPositionUVColorBuffer( - Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) const { - using VS = PorterDuffBlendPipeline::VertexShader; - - auto vertex_count = vertices_.size(); - auto uv_transform = - texture_coverage.GetNormalizingTransform() * effect_transform; - auto has_texture_coordinates = HasTextureCoordinates(); - auto has_colors = HasVertexColors(); - - size_t total_vtx_bytes = vertices_.size() * sizeof(VS::PerVertexData); - auto vertex_buffer = renderer.GetTransientsBuffer().Emplace( - total_vtx_bytes, alignof(VS::PerVertexData), [&](uint8_t* data) { - VS::PerVertexData* vtx_contents = - reinterpret_cast(data); - for (auto i = 0u; i < vertices_.size(); i++) { - auto vertex = vertices_[i]; - auto texture_coord = - has_texture_coordinates ? texture_coordinates_[i] : vertices_[i]; - auto uv = uv_transform * texture_coord; - VS::PerVertexData vertex_data = { - .vertices = vertex, - .texture_coords = uv, - .color = has_colors ? colors_[i] : Color::BlackTransparent(), - }; - std::memcpy(vtx_contents++, &vertex_data, sizeof(VS::PerVertexData)); - } - }); - - BufferView index_buffer = {}; - auto index_count = indices_.size(); - size_t total_idx_bytes = index_count * sizeof(uint16_t); - if (index_count > 0) { - index_buffer = renderer.GetTransientsBuffer().Emplace( - indices_.data(), total_idx_bytes, alignof(uint16_t)); - } - - return GeometryResult{ - .type = GetPrimitiveType(), - .vertex_buffer = - { - .vertex_buffer = vertex_buffer, - .index_buffer = index_buffer, - .vertex_count = index_count > 0 ? index_count : vertex_count, - .index_type = - index_count > 0 ? IndexType::k16bit : IndexType::kNone, - }, - .transform = entity.GetShaderTransform(pass), - }; -} - -std::optional VerticesGeometry::GetCoverage( - const Matrix& transform) const { - return bounds_.TransformBounds(transform); -} } // namespace impeller diff --git a/impeller/entity/geometry/vertices_geometry.h b/impeller/entity/geometry/vertices_geometry.h index 57cebe106481c..d32bb6c1d10e4 100644 --- a/impeller/entity/geometry/vertices_geometry.h +++ b/impeller/entity/geometry/vertices_geometry.h @@ -10,55 +10,20 @@ namespace impeller { /// @brief A geometry that is created from a vertices object. -class VerticesGeometry final : public Geometry { +class VerticesGeometry : public Geometry { public: - enum class VertexMode { - kTriangles, - kTriangleStrip, - kTriangleFan, - }; + virtual GeometryResult GetPositionUVColorBuffer( + Rect texture_coverage, + Matrix effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const = 0; - VerticesGeometry(std::vector vertices, - std::vector indices, - std::vector texture_coordinates, - std::vector colors, - Rect bounds, - VerticesGeometry::VertexMode vertex_mode); + virtual bool HasVertexColors() const = 0; - ~VerticesGeometry() = default; + virtual bool HasTextureCoordinates() const = 0; - GeometryResult GetPositionUVColorBuffer(Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) const; - - // |Geometry| - GeometryResult GetPositionBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) const override; - - // |Geometry| - std::optional GetCoverage(const Matrix& transform) const override; - - bool HasVertexColors() const; - - bool HasTextureCoordinates() const; - - std::optional GetTextureCoordinateCoverge() const; - - private: - void NormalizeIndices(); - - PrimitiveType GetPrimitiveType() const; - - std::vector vertices_; - std::vector colors_; - std::vector texture_coordinates_; - std::vector indices_; - Rect bounds_; - VerticesGeometry::VertexMode vertex_mode_ = - VerticesGeometry::VertexMode::kTriangles; + virtual std::optional GetTextureCoordinateCoverge() const = 0; }; } // namespace impeller diff --git a/impeller/renderer/backend/gles/capabilities_gles.cc b/impeller/renderer/backend/gles/capabilities_gles.cc index b55d2fe54dc02..f4cb50d0574e9 100644 --- a/impeller/renderer/backend/gles/capabilities_gles.cc +++ b/impeller/renderer/backend/gles/capabilities_gles.cc @@ -181,6 +181,10 @@ bool CapabilitiesGLES::SupportsDeviceTransientTextures() const { return false; } +bool CapabilitiesGLES::SupportsTriangleFan() const { + return true; +} + PixelFormat CapabilitiesGLES::GetDefaultColorFormat() const { return PixelFormat::kR8G8B8A8UNormInt; } diff --git a/impeller/renderer/backend/gles/capabilities_gles.h b/impeller/renderer/backend/gles/capabilities_gles.h index d551acafac5d4..8485504b24c61 100644 --- a/impeller/renderer/backend/gles/capabilities_gles.h +++ b/impeller/renderer/backend/gles/capabilities_gles.h @@ -107,6 +107,9 @@ class CapabilitiesGLES final // |Capabilities| bool SupportsDeviceTransientTextures() const override; + // |Capabilities| + bool SupportsTriangleFan() const override; + // |Capabilities| PixelFormat GetDefaultColorFormat() const override; diff --git a/impeller/renderer/backend/gles/formats_gles.h b/impeller/renderer/backend/gles/formats_gles.h index 3cc28b675f976..9b3c9ff829067 100644 --- a/impeller/renderer/backend/gles/formats_gles.h +++ b/impeller/renderer/backend/gles/formats_gles.h @@ -26,6 +26,8 @@ constexpr GLenum ToMode(PrimitiveType primitive_type) { return GL_LINE_STRIP; case PrimitiveType::kPoint: return GL_POINTS; + case PrimitiveType::kTriangleFan: + return GL_TRIANGLE_FAN; } FML_UNREACHABLE(); } diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index fdd3202edd67f..85bf772cfe51d 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -68,6 +68,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { .SetSupportsReadFromResolve(true) .SetSupportsDeviceTransientTextures(true) .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt) + .SetSupportsTriangleFan(false) .Build(); } diff --git a/impeller/renderer/backend/metal/formats_mtl.h b/impeller/renderer/backend/metal/formats_mtl.h index d1a9b0d94e40a..53ba4583b7f57 100644 --- a/impeller/renderer/backend/metal/formats_mtl.h +++ b/impeller/renderer/backend/metal/formats_mtl.h @@ -159,6 +159,9 @@ constexpr MTLPrimitiveType ToMTLPrimitiveType(PrimitiveType type) { return MTLPrimitiveTypeLineStrip; case PrimitiveType::kPoint: return MTLPrimitiveTypePoint; + case PrimitiveType::kTriangleFan: + // UNSUPPORTED + return MTLPrimitiveTypePoint; } return MTLPrimitiveTypePoint; } diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index ad72a03fde6a5..51ca7fe3cd4c7 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -708,4 +708,8 @@ CapabilitiesVK::GetSupportedFRCRate(CompressionType compression_type, return std::nullopt; } +bool CapabilitiesVK::SupportsTriangleFan() const { + return true; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h index 1024f2f822218..2ff61b1167422 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -238,6 +238,9 @@ class CapabilitiesVK final : public Capabilities, // |Capabilities| bool SupportsDeviceTransientTextures() const override; + // |Capabilities| + bool SupportsTriangleFan() const override; + // |Capabilities| PixelFormat GetDefaultColorFormat() const override; diff --git a/impeller/renderer/backend/vulkan/formats_vk.h b/impeller/renderer/backend/vulkan/formats_vk.h index 7524e9ef36752..8ff6ac4a8f78f 100644 --- a/impeller/renderer/backend/vulkan/formats_vk.h +++ b/impeller/renderer/backend/vulkan/formats_vk.h @@ -383,6 +383,8 @@ constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive) { return vk::PrimitiveTopology::eLineStrip; case PrimitiveType::kPoint: return vk::PrimitiveTopology::ePointList; + case PrimitiveType::kTriangleFan: + return vk::PrimitiveTopology::eTriangleFan; } FML_UNREACHABLE(); diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc index 395fecf1b81f1..5b6914b1fcbb7 100644 --- a/impeller/renderer/capabilities.cc +++ b/impeller/renderer/capabilities.cc @@ -55,6 +55,9 @@ class StandardCapabilities final : public Capabilities { return supports_decal_sampler_address_mode_; } + // |Capabilities| + bool SupportsTriangleFan() const override { return supports_triangle_fan_; } + // |Capabilities| PixelFormat GetDefaultColorFormat() const override { return default_color_format_; @@ -90,6 +93,7 @@ class StandardCapabilities final : public Capabilities { bool supports_read_from_resolve, bool supports_decal_sampler_address_mode, bool supports_device_transient_textures, + bool supports_triangle_fan, PixelFormat default_color_format, PixelFormat default_stencil_format, PixelFormat default_depth_stencil_format, @@ -104,6 +108,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_triangle_fan_(supports_triangle_fan), default_color_format_(default_color_format), default_stencil_format_(default_stencil_format), default_depth_stencil_format_(default_depth_stencil_format), @@ -120,6 +125,7 @@ class StandardCapabilities final : public Capabilities { bool supports_read_from_resolve_ = false; bool supports_decal_sampler_address_mode_ = false; bool supports_device_transient_textures_ = false; + bool supports_triangle_fan_ = false; PixelFormat default_color_format_ = PixelFormat::kUnknown; PixelFormat default_stencil_format_ = PixelFormat::kUnknown; PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown; @@ -209,6 +215,11 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultGlyphAtlasFormat( return *this; } +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsTriangleFan(bool value) { + supports_triangle_fan_ = value; + return *this; +} + std::unique_ptr CapabilitiesBuilder::Build() { return std::unique_ptr(new StandardCapabilities( // supports_offscreen_msaa_, // @@ -220,6 +231,7 @@ std::unique_ptr CapabilitiesBuilder::Build() { supports_read_from_resolve_, // supports_decal_sampler_address_mode_, // supports_device_transient_textures_, // + supports_triangle_fan_, // 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 b86a90fa868de..576a7c1dd9490 100644 --- a/impeller/renderer/capabilities.h +++ b/impeller/renderer/capabilities.h @@ -83,6 +83,9 @@ class Capabilities { /// This feature is especially useful for MSAA and stencils. virtual bool SupportsDeviceTransientTextures() const = 0; + /// @brief Whether the primitive type TriangleFan is supported by the backend. + virtual bool SupportsTriangleFan() const = 0; + /// @brief Returns a supported `PixelFormat` for textures that store /// 4-channel colors (red/green/blue/alpha). virtual PixelFormat GetDefaultColorFormat() const = 0; @@ -145,6 +148,8 @@ class CapabilitiesBuilder { CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value); + CapabilitiesBuilder& SetSupportsTriangleFan(bool value); + std::unique_ptr Build(); private: @@ -157,6 +162,7 @@ class CapabilitiesBuilder { bool supports_read_from_resolve_ = false; bool supports_decal_sampler_address_mode_ = false; bool supports_device_transient_textures_ = false; + bool supports_triangle_fan_ = 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 e92d37341082e..d6dc30e4b904c 100644 --- a/impeller/renderer/capabilities_unittests.cc +++ b/impeller/renderer/capabilities_unittests.cc @@ -27,6 +27,7 @@ CAPABILITY_TEST(SupportsComputeSubgroups, false); CAPABILITY_TEST(SupportsReadFromResolve, false); CAPABILITY_TEST(SupportsDecalSamplerAddressMode, false); CAPABILITY_TEST(SupportsDeviceTransientTextures, false); +CAPABILITY_TEST(SupportsTriangleFan, false); TEST(CapabilitiesTest, DefaultColorFormat) { auto defaults = CapabilitiesBuilder().Build(); diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index b1b1ff6964233..6b80affd3a171 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -208,6 +208,7 @@ class MockCapabilities : public Capabilities { MOCK_METHOD(bool, SupportsReadFromResolve, (), (const, override)); MOCK_METHOD(bool, SupportsDecalSamplerAddressMode, (), (const, override)); MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override)); + MOCK_METHOD(bool, SupportsTriangleFan, (), (const override)); MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override)); MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override)); MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override)); From b5c7aa2b9fab69f9fd24bbbe13ab0ce779809796 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 23 Sep 2024 11:40:12 -0700 Subject: [PATCH 2/2] ++ --- impeller/display_list/dl_vertices_geometry.h | 2 +- impeller/renderer/backend/metal/formats_mtl.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/impeller/display_list/dl_vertices_geometry.h b/impeller/display_list/dl_vertices_geometry.h index a985433ae7bf4..c433d2fe55d89 100644 --- a/impeller/display_list/dl_vertices_geometry.h +++ b/impeller/display_list/dl_vertices_geometry.h @@ -51,7 +51,7 @@ class DlVerticesGeometry final : public VerticesGeometry { const std::shared_ptr vertices_; std::vector indices_; - bool performed_normalization_; + bool performed_normalization_ = false; Rect bounds_; }; diff --git a/impeller/renderer/backend/metal/formats_mtl.h b/impeller/renderer/backend/metal/formats_mtl.h index 53ba4583b7f57..432a1cfa5c768 100644 --- a/impeller/renderer/backend/metal/formats_mtl.h +++ b/impeller/renderer/backend/metal/formats_mtl.h @@ -160,7 +160,8 @@ constexpr MTLPrimitiveType ToMTLPrimitiveType(PrimitiveType type) { case PrimitiveType::kPoint: return MTLPrimitiveTypePoint; case PrimitiveType::kTriangleFan: - // UNSUPPORTED + // Callers are expected to perform a capability check for triangle fan + // support. return MTLPrimitiveTypePoint; } return MTLPrimitiveTypePoint;