diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 239ac4d458f55..eece0b9e72c77 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1626,14 +1626,15 @@ ORIGIN: ../../../flutter/impeller/scene/mesh.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/mesh.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/node.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/node.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/scene/pipeline_key.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene_context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene_context.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene_encoder.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/scene_encoder.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/scene/shaders/geometry.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/scene/shaders/unlit.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/scene/shaders/unskinned.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart + ../../../flutter/LICENSE @@ -4075,14 +4076,15 @@ FILE: ../../../flutter/impeller/scene/mesh.cc FILE: ../../../flutter/impeller/scene/mesh.h FILE: ../../../flutter/impeller/scene/node.cc FILE: ../../../flutter/impeller/scene/node.h +FILE: ../../../flutter/impeller/scene/pipeline_key.h FILE: ../../../flutter/impeller/scene/scene.cc FILE: ../../../flutter/impeller/scene/scene.h FILE: ../../../flutter/impeller/scene/scene_context.cc FILE: ../../../flutter/impeller/scene/scene_context.h FILE: ../../../flutter/impeller/scene/scene_encoder.cc FILE: ../../../flutter/impeller/scene/scene_encoder.h -FILE: ../../../flutter/impeller/scene/shaders/geometry.vert FILE: ../../../flutter/impeller/scene/shaders/unlit.frag +FILE: ../../../flutter/impeller/scene/shaders/unskinned.vert FILE: ../../../flutter/impeller/tessellator/c/tessellator.cc FILE: ../../../flutter/impeller/tessellator/c/tessellator.h FILE: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart diff --git a/impeller/scene/BUILD.gn b/impeller/scene/BUILD.gn index b13a563e72e7b..4dbbc755d57a2 100644 --- a/impeller/scene/BUILD.gn +++ b/impeller/scene/BUILD.gn @@ -16,6 +16,7 @@ impeller_component("scene") { "mesh.h", "node.cc", "node.h", + "pipeline_key.h", "scene.cc", "scene.h", "scene_context.cc", diff --git a/impeller/scene/geometry.cc b/impeller/scene/geometry.cc index 1cbff8188c320..7ce1f2eb5fc8d 100644 --- a/impeller/scene/geometry.cc +++ b/impeller/scene/geometry.cc @@ -15,8 +15,7 @@ #include "impeller/renderer/vertex_buffer.h" #include "impeller/renderer/vertex_buffer_builder.h" #include "impeller/scene/importer/scene_flatbuffers.h" -#include "impeller/scene/shaders/geometry.vert.h" -#include "third_party/flatbuffers/include/flatbuffers/vector.h" +#include "impeller/scene/shaders/unskinned.vert.h" namespace impeller { namespace scene { @@ -111,8 +110,14 @@ void CuboidGeometry::SetSize(Vector3 size) { size_ = size; } +// |Geometry| +GeometryType CuboidGeometry::GetGeometryType() const { + return GeometryType::kUnskinned; +} + +// |Geometry| VertexBuffer CuboidGeometry::GetVertexBuffer(Allocator& allocator) const { - VertexBufferBuilder builder; + VertexBufferBuilder builder; // Layout: position, normal, tangent, uv builder.AddVertices({ // Front. @@ -132,6 +137,19 @@ VertexBuffer CuboidGeometry::GetVertexBuffer(Allocator& allocator) const { return builder.CreateVertexBuffer(allocator); } +// |Geometry| +void CuboidGeometry::BindToCommand(const SceneContext& scene_context, + HostBuffer& buffer, + const Matrix& transform, + Command& command) const { + command.BindVertices( + GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator())); + + UnskinnedVertexShader::VertInfo info; + info.mvp = transform; + UnskinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info)); +} + //------------------------------------------------------------------------------ /// VertexBufferGeometry /// @@ -144,9 +162,28 @@ void VertexBufferGeometry::SetVertexBuffer(VertexBuffer vertex_buffer) { vertex_buffer_ = std::move(vertex_buffer); } +// |Geometry| +GeometryType VertexBufferGeometry::GetGeometryType() const { + return GeometryType::kUnskinned; +} + +// |Geometry| VertexBuffer VertexBufferGeometry::GetVertexBuffer(Allocator& allocator) const { return vertex_buffer_; } +// |Geometry| +void VertexBufferGeometry::BindToCommand(const SceneContext& scene_context, + HostBuffer& buffer, + const Matrix& transform, + Command& command) const { + command.BindVertices( + GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator())); + + UnskinnedVertexShader::VertInfo info; + info.mvp = transform; + UnskinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info)); +} + } // namespace scene } // namespace impeller diff --git a/impeller/scene/geometry.h b/impeller/scene/geometry.h index 641762ab72b88..f056fe11eb8a5 100644 --- a/impeller/scene/geometry.h +++ b/impeller/scene/geometry.h @@ -7,11 +7,16 @@ #include #include "flutter/fml/macros.h" +#include "impeller/geometry/matrix.h" #include "impeller/geometry/vector.h" #include "impeller/renderer/allocator.h" +#include "impeller/renderer/command.h" #include "impeller/renderer/device_buffer.h" +#include "impeller/renderer/host_buffer.h" #include "impeller/renderer/vertex_buffer.h" #include "impeller/scene/importer/scene_flatbuffers.h" +#include "impeller/scene/pipeline_key.h" +#include "impeller/scene/scene_context.h" namespace impeller { namespace scene { @@ -32,7 +37,14 @@ class Geometry { const fb::MeshPrimitive& mesh, Allocator& allocator); + virtual GeometryType GetGeometryType() const = 0; + virtual VertexBuffer GetVertexBuffer(Allocator& allocator) const = 0; + + virtual void BindToCommand(const SceneContext& scene_context, + HostBuffer& buffer, + const Matrix& transform, + Command& command) const = 0; }; class CuboidGeometry final : public Geometry { @@ -43,9 +55,18 @@ class CuboidGeometry final : public Geometry { void SetSize(Vector3 size); + // |Geometry| + GeometryType GetGeometryType() const override; + // |Geometry| VertexBuffer GetVertexBuffer(Allocator& allocator) const override; + // |Geometry| + void BindToCommand(const SceneContext& scene_context, + HostBuffer& buffer, + const Matrix& transform, + Command& command) const override; + private: Vector3 size_; @@ -60,9 +81,18 @@ class VertexBufferGeometry final : public Geometry { void SetVertexBuffer(VertexBuffer vertex_buffer); + // |Geometry| + GeometryType GetGeometryType() const override; + // |Geometry| VertexBuffer GetVertexBuffer(Allocator& allocator) const override; + // |Geometry| + void BindToCommand(const SceneContext& scene_context, + HostBuffer& buffer, + const Matrix& transform, + Command& command) const override; + private: VertexBuffer vertex_buffer_; diff --git a/impeller/scene/material.cc b/impeller/scene/material.cc index 7b4c59a684f70..9ea9655a74ae2 100644 --- a/impeller/scene/material.cc +++ b/impeller/scene/material.cc @@ -6,6 +6,7 @@ #include "impeller/renderer/formats.h" #include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/sampler_library.h" +#include "impeller/scene/pipeline_key.h" #include "impeller/scene/scene_context.h" #include "impeller/scene/shaders/unlit.frag.h" @@ -64,10 +65,8 @@ void UnlitMaterial::SetVertexColorWeight(Scalar weight) { } // |Material| -std::shared_ptr> UnlitMaterial::GetPipeline( - const SceneContext& scene_context, - const RenderPass& pass) const { - return scene_context.GetUnlitPipeline(GetContextOptions(pass)); +MaterialType UnlitMaterial::GetMaterialType() const { + return MaterialType::kUnlit; } // |Material| @@ -75,11 +74,10 @@ void UnlitMaterial::BindToCommand(const SceneContext& scene_context, HostBuffer& buffer, Command& command) const { // Uniform buffer. - UnlitPipeline::FragmentShader::FragInfo info; + UnlitFragmentShader::FragInfo info; info.color = color_; info.vertex_color_weight = vertex_color_weight_; - UnlitPipeline::FragmentShader::BindFragInfo(command, - buffer.EmplaceUniform(info)); + UnlitFragmentShader::BindFragInfo(command, buffer.EmplaceUniform(info)); // Textures. SamplerDescriptor sampler_descriptor; @@ -87,7 +85,7 @@ void UnlitMaterial::BindToCommand(const SceneContext& scene_context, sampler_descriptor.min_filter = MinMagFilter::kLinear; sampler_descriptor.mag_filter = MinMagFilter::kLinear; sampler_descriptor.mip_filter = MipFilter::kLinear; - UnlitPipeline::FragmentShader::BindBaseColorTexture( + UnlitFragmentShader::BindBaseColorTexture( command, color_texture_ ? color_texture_ : scene_context.GetPlaceholderTexture(), scene_context.GetContext()->GetSamplerLibrary()->GetSampler( @@ -134,10 +132,9 @@ void StandardMaterial::SetEnvironmentMap( } // |Material| -std::shared_ptr> StandardMaterial::GetPipeline( - const SceneContext& scene_context, - const RenderPass& pass) const { - return nullptr; +MaterialType StandardMaterial::GetMaterialType() const { + // TODO(bdero): Replace this once a PBR shader has landed. + return MaterialType::kUnlit; } // |Material| diff --git a/impeller/scene/material.h b/impeller/scene/material.h index 5814986b67a26..d289a6e8bbd4d 100644 --- a/impeller/scene/material.h +++ b/impeller/scene/material.h @@ -10,6 +10,7 @@ #include "impeller/renderer/formats.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/texture.h" +#include "impeller/scene/pipeline_key.h" namespace impeller { namespace scene { @@ -47,16 +48,15 @@ class Material { void SetTranslucent(bool is_translucent); - virtual std::shared_ptr> GetPipeline( - const SceneContext& scene_context, - const RenderPass& pass) const = 0; + SceneContextOptions GetContextOptions(const RenderPass& pass) const; + + virtual MaterialType GetMaterialType() const = 0; + virtual void BindToCommand(const SceneContext& scene_context, HostBuffer& buffer, Command& command) const = 0; protected: - SceneContextOptions GetContextOptions(const RenderPass& pass) const; - BlendConfig blend_config_; StencilConfig stencil_config_; bool is_translucent_ = false; @@ -73,9 +73,7 @@ class UnlitMaterial final : public Material { void SetVertexColorWeight(Scalar weight); // |Material| - std::shared_ptr> GetPipeline( - const SceneContext& scene_context, - const RenderPass& pass) const override; + MaterialType GetMaterialType() const override; // |Material| void BindToCommand(const SceneContext& scene_context, @@ -104,9 +102,7 @@ class StandardMaterial final : public Material { void SetEnvironmentMap(std::shared_ptr environment_map); // |Material| - std::shared_ptr> GetPipeline( - const SceneContext& scene_context, - const RenderPass& pass) const override; + MaterialType GetMaterialType() const override; // |Material| void BindToCommand(const SceneContext& scene_context, diff --git a/impeller/scene/pipeline_key.h b/impeller/scene/pipeline_key.h new file mode 100644 index 0000000000000..c4cd3e07c6421 --- /dev/null +++ b/impeller/scene/pipeline_key.h @@ -0,0 +1,41 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include "flutter/fml/hash_combine.h" + +namespace impeller { +namespace scene { + +enum class GeometryType { + kUnskinned = 0, + kLastType = kUnskinned, +}; +enum class MaterialType { + kUnlit = 0, + kLastType = kUnlit, +}; + +struct PipelineKey { + GeometryType geometry_type = GeometryType::kUnskinned; + MaterialType material_type = MaterialType::kUnlit; + + struct Hash { + constexpr std::size_t operator()(const PipelineKey& o) const { + return fml::HashCombine(o.geometry_type, o.material_type); + } + }; + + struct Equal { + constexpr bool operator()(const PipelineKey& lhs, + const PipelineKey& rhs) const { + return lhs.geometry_type == rhs.geometry_type && + lhs.material_type == rhs.material_type; + } + }; +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_context.cc b/impeller/scene/scene_context.cc index fbb6f02f677d7..359f18b24582c 100644 --- a/impeller/scene/scene_context.cc +++ b/impeller/scene/scene_context.cc @@ -4,6 +4,9 @@ #include "impeller/scene/scene_context.h" #include "impeller/renderer/formats.h" +#include "impeller/scene/material.h" +#include "impeller/scene/shaders/unlit.frag.h" +#include "impeller/scene/shaders/unskinned.vert.h" namespace impeller { namespace scene { @@ -26,25 +29,15 @@ void SceneContextOptions::ApplyToPipelineDescriptor( desc.SetPrimitiveType(primitive_type); } -template -static std::unique_ptr CreateDefaultPipeline( - const Context& context) { - auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context); - if (!desc.has_value()) { - return nullptr; - } - // Apply default ContentContextOptions to the descriptor. - SceneContextOptions{}.ApplyToPipelineDescriptor(*desc); - return std::make_unique(context, desc); -} - SceneContext::SceneContext(std::shared_ptr context) : context_(std::move(context)) { if (!context_ || !context_->IsValid()) { return; } - unlit_pipeline_[{}] = CreateDefaultPipeline(*context_); + pipelines_[{PipelineKey{GeometryType::kUnskinned, MaterialType::kUnlit}}] = + MakePipelineVariants( + *context_); { impeller::TextureDescriptor texture_descriptor; @@ -72,6 +65,18 @@ SceneContext::SceneContext(std::shared_ptr context) SceneContext::~SceneContext() = default; +std::shared_ptr> SceneContext::GetPipeline( + PipelineKey key, + SceneContextOptions opts) const { + if (!IsValid()) { + return nullptr; + } + if (auto found = pipelines_.find(key); found != pipelines_.end()) { + return found->second->GetPipeline(opts); + } + return nullptr; +} + bool SceneContext::IsValid() const { return is_valid_; } diff --git a/impeller/scene/scene_context.h b/impeller/scene/scene_context.h index 1e1a2a6b57df1..40c0643d28f21 100644 --- a/impeller/scene/scene_context.h +++ b/impeller/scene/scene_context.h @@ -7,16 +7,13 @@ #include #include "impeller/renderer/context.h" +#include "impeller/renderer/pipeline.h" #include "impeller/renderer/pipeline_descriptor.h" -#include "impeller/scene/shaders/geometry.vert.h" -#include "impeller/scene/shaders/unlit.frag.h" +#include "impeller/scene/pipeline_key.h" namespace impeller { namespace scene { -using UnlitPipeline = - RenderPipelineT; - struct SceneContextOptions { SampleCount sample_count = SampleCount::kCount1; PrimitiveType primitive_type = PrimitiveType::kTriangle; @@ -46,52 +43,79 @@ class SceneContext { bool IsValid() const; + std::shared_ptr> GetPipeline( + PipelineKey key, + SceneContextOptions opts) const; + std::shared_ptr GetContext() const; std::shared_ptr GetPlaceholderTexture() const; - std::shared_ptr> GetUnlitPipeline( - SceneContextOptions opts) const { - return GetPipeline(unlit_pipeline_, opts); - } - private: - template - using Variants = std::unordered_map, - SceneContextOptions::Hash, - SceneContextOptions::Equal>; - template - std::shared_ptr> GetPipeline( - Variants& container, - SceneContextOptions opts) const { - if (!IsValid()) { - return nullptr; - } + class PipelineVariants { + public: + virtual ~PipelineVariants() = default; + + virtual std::shared_ptr> GetPipeline( + SceneContextOptions opts) = 0; + }; - if (auto found = container.find(opts); found != container.end()) { - return found->second->WaitAndGet(); + template + class PipelineVariantsT final : public PipelineVariants { + public: + explicit PipelineVariantsT(Context& context) { + auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context); + // Apply default ContentContextOptions to the descriptor. + SceneContextOptions{}.ApplyToPipelineDescriptor(*desc); + variants_[{}] = std::make_unique(context, desc); + }; + + // |PipelineCollection| + std::shared_ptr> GetPipeline( + SceneContextOptions opts) { + if (auto found = variants_.find(opts); found != variants_.end()) { + return found->second->WaitAndGet(); + } + + auto prototype = variants_.find({}); + + // The prototype must always be initialized in the constructor. + FML_CHECK(prototype != variants_.end()); + + auto variant_future = prototype->second->WaitAndGet()->CreateVariant( + [&opts, variants_count = variants_.size()](PipelineDescriptor& desc) { + opts.ApplyToPipelineDescriptor(desc); + desc.SetLabel( + SPrintF("%s V#%zu", desc.GetLabel().c_str(), variants_count)); + }); + auto variant = std::make_unique(std::move(variant_future)); + auto variant_pipeline = variant->WaitAndGet(); + variants_[opts] = std::move(variant); + return variant_pipeline; } - auto prototype = container.find({}); - - // The prototype must always be initialized in the constructor. - FML_CHECK(prototype != container.end()); - - auto variant_future = prototype->second->WaitAndGet()->CreateVariant( - [&opts, variants_count = container.size()](PipelineDescriptor& desc) { - opts.ApplyToPipelineDescriptor(desc); - desc.SetLabel( - SPrintF("%s V#%zu", desc.GetLabel().c_str(), variants_count)); - }); - auto variant = std::make_unique(std::move(variant_future)); - auto variant_pipeline = variant->WaitAndGet(); - container[opts] = std::move(variant); - return variant_pipeline; + private: + std::unordered_map, + SceneContextOptions::Hash, + SceneContextOptions::Equal> + variants_; + }; + + template + std::unique_ptr MakePipelineVariants(Context& context) { + return std::make_unique< + PipelineVariantsT>>( + context); } + std::unordered_map, + PipelineKey::Hash, + PipelineKey::Equal> + pipelines_; + std::shared_ptr context_; - mutable Variants unlit_pipeline_; bool is_valid_ = false; // A 1x1 opaque white texture that can be used as a placeholder binding. diff --git a/impeller/scene/scene_encoder.cc b/impeller/scene/scene_encoder.cc index 1f3ffd8f7e549..e3376516a2f2f 100644 --- a/impeller/scene/scene_encoder.cc +++ b/impeller/scene/scene_encoder.cc @@ -9,7 +9,6 @@ #include "impeller/renderer/render_target.h" #include "impeller/scene/scene_context.h" #include "impeller/scene/scene_encoder.h" -#include "impeller/scene/shaders/geometry.vert.h" namespace impeller { namespace scene { @@ -32,17 +31,16 @@ static void EncodeCommand(const SceneContext& scene_context, cmd.stencil_reference = 0; // TODO(bdero): Configurable stencil ref per-command. - cmd.BindVertices(scene_command.geometry->GetVertexBuffer( - *scene_context.GetContext()->GetResourceAllocator())); + cmd.pipeline = scene_context.GetPipeline( + PipelineKey{scene_command.geometry->GetGeometryType(), + scene_command.material->GetMaterialType()}, + scene_command.material->GetContextOptions(render_pass)); - cmd.pipeline = - scene_command.material->GetPipeline(scene_context, render_pass); + scene_command.geometry->BindToCommand( + scene_context, host_buffer, view_transform * scene_command.transform, + cmd); scene_command.material->BindToCommand(scene_context, host_buffer, cmd); - GeometryVertexShader::VertInfo info; - info.mvp = view_transform * scene_command.transform; - GeometryVertexShader::BindVertInfo(cmd, host_buffer.EmplaceUniform(info)); - render_pass.AddCommand(std::move(cmd)); } diff --git a/impeller/scene/shaders/BUILD.gn b/impeller/scene/shaders/BUILD.gn index a802c63f35390..f17b6719a7b58 100644 --- a/impeller/scene/shaders/BUILD.gn +++ b/impeller/scene/shaders/BUILD.gn @@ -8,7 +8,7 @@ impeller_shaders("shaders") { name = "scene" shaders = [ - "geometry.vert", + "unskinned.vert", "unlit.frag", ] } diff --git a/impeller/scene/shaders/geometry.vert b/impeller/scene/shaders/unskinned.vert similarity index 100% rename from impeller/scene/shaders/geometry.vert rename to impeller/scene/shaders/unskinned.vert