[Impeller Scene] Command encoding (flutter/engine#37977)
This commit is contained in:
@@ -6,6 +6,12 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "impeller/geometry/point.h"
|
||||
#include "impeller/geometry/vector.h"
|
||||
#include "impeller/renderer/formats.h"
|
||||
#include "impeller/renderer/vertex_buffer_builder.h"
|
||||
#include "impeller/scene/shaders/geometry.vert.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace scene {
|
||||
|
||||
@@ -27,9 +33,19 @@ void CuboidGeometry::SetSize(Vector3 size) {
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
VertexBuffer CuboidGeometry::GetVertexBuffer(
|
||||
std::shared_ptr<Allocator>& allocator) const {
|
||||
return {};
|
||||
VertexBuffer CuboidGeometry::GetVertexBuffer(Allocator& allocator) const {
|
||||
VertexBufferBuilder<GeometryVertexShader::PerVertexData, uint16_t> builder;
|
||||
// Layout: position, normal, tangent, uv
|
||||
builder.AddVertices({
|
||||
// Front.
|
||||
{Vector3(0, 0, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(0, 0)},
|
||||
{Vector3(1, 0, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(1, 0)},
|
||||
{Vector3(1, 1, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(1, 1)},
|
||||
{Vector3(1, 1, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(1, 1)},
|
||||
{Vector3(0, 1, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(0, 1)},
|
||||
{Vector3(0, 0, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Point(0, 0)},
|
||||
});
|
||||
return builder.CreateVertexBuffer(allocator);
|
||||
}
|
||||
|
||||
} // namespace scene
|
||||
|
||||
@@ -19,19 +19,16 @@ class Geometry {
|
||||
public:
|
||||
static std::shared_ptr<CuboidGeometry> MakeCuboid(Vector3 size);
|
||||
|
||||
private:
|
||||
virtual VertexBuffer GetVertexBuffer(
|
||||
std::shared_ptr<Allocator>& allocator) const = 0;
|
||||
virtual VertexBuffer GetVertexBuffer(Allocator& allocator) const = 0;
|
||||
};
|
||||
|
||||
class CuboidGeometry final : public Geometry {
|
||||
public:
|
||||
void SetSize(Vector3 size);
|
||||
|
||||
private:
|
||||
VertexBuffer GetVertexBuffer(
|
||||
std::shared_ptr<Allocator>& allocator) const override;
|
||||
VertexBuffer GetVertexBuffer(Allocator& allocator) const override;
|
||||
|
||||
private:
|
||||
Vector3 size_;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/scene/material.h"
|
||||
#include "impeller/renderer/formats.h"
|
||||
#include "impeller/renderer/sampler_descriptor.h"
|
||||
#include "impeller/renderer/sampler_library.h"
|
||||
#include "impeller/scene/scene_context.h"
|
||||
#include "impeller/scene/shaders/unlit.frag.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -33,6 +38,11 @@ void Material::SetTranslucent(bool is_translucent) {
|
||||
is_translucent_ = is_translucent;
|
||||
}
|
||||
|
||||
SceneContextOptions Material::GetContextOptions(const RenderPass& pass) const {
|
||||
// TODO(bdero): Pipeline blend and stencil config.
|
||||
return {.sample_count = pass.GetRenderTarget().GetSampleCount()};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// UnlitMaterial
|
||||
///
|
||||
@@ -41,6 +51,40 @@ void UnlitMaterial::SetColor(Color color) {
|
||||
color_ = color;
|
||||
}
|
||||
|
||||
void UnlitMaterial::SetColorTexture(std::shared_ptr<Texture> color_texture) {
|
||||
color_texture_ = std::move(color_texture);
|
||||
}
|
||||
|
||||
// |Material|
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> UnlitMaterial::GetPipeline(
|
||||
const SceneContext& scene_context,
|
||||
const RenderPass& pass) const {
|
||||
return scene_context.GetUnlitPipeline(GetContextOptions(pass));
|
||||
}
|
||||
|
||||
// |Material|
|
||||
void UnlitMaterial::BindToCommand(const SceneContext& scene_context,
|
||||
HostBuffer& buffer,
|
||||
Command& command) const {
|
||||
// Uniform buffer.
|
||||
UnlitPipeline::FragmentShader::FragInfo info;
|
||||
info.color = color_;
|
||||
UnlitPipeline::FragmentShader::BindFragInfo(command,
|
||||
buffer.EmplaceUniform(info));
|
||||
|
||||
// Textures.
|
||||
SamplerDescriptor sampler_descriptor;
|
||||
sampler_descriptor.label = "Trilinear";
|
||||
sampler_descriptor.min_filter = MinMagFilter::kLinear;
|
||||
sampler_descriptor.mag_filter = MinMagFilter::kLinear;
|
||||
sampler_descriptor.mip_filter = MipFilter::kLinear;
|
||||
UnlitPipeline::FragmentShader::BindBaseColorTexture(
|
||||
command,
|
||||
color_texture_ ? color_texture_ : scene_context.GetPlaceholderTexture(),
|
||||
scene_context.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
sampler_descriptor));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// StandardMaterial
|
||||
///
|
||||
@@ -78,5 +122,17 @@ void StandardMaterial::SetEnvironmentMap(
|
||||
environment_map_ = std::move(environment_map);
|
||||
}
|
||||
|
||||
// |Material|
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> StandardMaterial::GetPipeline(
|
||||
const SceneContext& scene_context,
|
||||
const RenderPass& pass) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// |Material|
|
||||
void StandardMaterial::BindToCommand(const SceneContext& scene_context,
|
||||
HostBuffer& buffer,
|
||||
Command& command) const {}
|
||||
|
||||
} // namespace scene
|
||||
} // namespace impeller
|
||||
|
||||
@@ -8,11 +8,16 @@
|
||||
|
||||
#include "impeller/geometry/scalar.h"
|
||||
#include "impeller/renderer/formats.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/texture.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace scene {
|
||||
|
||||
class SceneContext;
|
||||
struct SceneContextOptions;
|
||||
class Geometry;
|
||||
|
||||
class UnlitMaterial;
|
||||
class StandardMaterial;
|
||||
|
||||
@@ -40,7 +45,16 @@ class Material {
|
||||
|
||||
void SetTranslucent(bool is_translucent);
|
||||
|
||||
virtual std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
|
||||
const SceneContext& scene_context,
|
||||
const RenderPass& pass) 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;
|
||||
@@ -50,8 +64,21 @@ class UnlitMaterial final : public Material {
|
||||
public:
|
||||
void SetColor(Color color);
|
||||
|
||||
void SetColorTexture(std::shared_ptr<Texture> color_texture);
|
||||
|
||||
// |Material|
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
|
||||
const SceneContext& scene_context,
|
||||
const RenderPass& pass) const override;
|
||||
|
||||
// |Material|
|
||||
void BindToCommand(const SceneContext& scene_context,
|
||||
HostBuffer& buffer,
|
||||
Command& command) const override;
|
||||
|
||||
private:
|
||||
Color color_;
|
||||
Color color_ = Color::White();
|
||||
std::shared_ptr<Texture> color_texture_;
|
||||
};
|
||||
|
||||
class StandardMaterial final : public Material {
|
||||
@@ -67,8 +94,18 @@ class StandardMaterial final : public Material {
|
||||
|
||||
void SetEnvironmentMap(std::shared_ptr<Texture> environment_map);
|
||||
|
||||
// |Material|
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
|
||||
const SceneContext& scene_context,
|
||||
const RenderPass& pass) const override;
|
||||
|
||||
// |Material|
|
||||
void BindToCommand(const SceneContext& scene_context,
|
||||
HostBuffer& buffer,
|
||||
Command& command) const override;
|
||||
|
||||
private:
|
||||
Color albedo_ = Color::CornflowerBlue();
|
||||
Color albedo_ = Color::White();
|
||||
Scalar roughness_ = 0.5;
|
||||
Scalar metallic_ = 0.5;
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ bool Scene::Render(const RenderTarget& render_target,
|
||||
}
|
||||
|
||||
// Encode the commands.
|
||||
|
||||
std::shared_ptr<CommandBuffer> command_buffer =
|
||||
encoder.BuildSceneCommandBuffer(*scene_context_->GetContext(),
|
||||
render_target);
|
||||
encoder.BuildSceneCommandBuffer(*scene_context_, render_target);
|
||||
|
||||
// TODO(bdero): Do post processing.
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/scene/scene_context.h"
|
||||
#include "impeller/renderer/formats.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace scene {
|
||||
@@ -33,6 +34,27 @@ SceneContext::SceneContext(std::shared_ptr<Context> context)
|
||||
|
||||
unlit_pipeline_[{}] = CreateDefaultPipeline<UnlitPipeline>(*context_);
|
||||
|
||||
{
|
||||
impeller::TextureDescriptor texture_descriptor;
|
||||
texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
|
||||
texture_descriptor.format = PixelFormat::kDefaultColor;
|
||||
texture_descriptor.size = {1, 1};
|
||||
texture_descriptor.mip_count = 1u;
|
||||
|
||||
placeholder_texture_ =
|
||||
context_->GetResourceAllocator()->CreateTexture(texture_descriptor);
|
||||
if (!placeholder_texture_) {
|
||||
FML_DLOG(ERROR) << "Could not create placeholder texture.";
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t pixel[] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
if (!placeholder_texture_->SetContents(pixel, 4, 0)) {
|
||||
FML_DLOG(ERROR) << "Could not set contents of placeholder texture.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
@@ -46,5 +68,9 @@ std::shared_ptr<Context> SceneContext::GetContext() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> SceneContext::GetPlaceholderTexture() const {
|
||||
return placeholder_texture_;
|
||||
}
|
||||
|
||||
} // namespace scene
|
||||
} // namespace impeller
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/renderer/pipeline_descriptor.h"
|
||||
#include "impeller/scene/shaders/geometry.vert.h"
|
||||
@@ -46,22 +48,19 @@ class SceneContext {
|
||||
|
||||
std::shared_ptr<Context> GetContext() const;
|
||||
|
||||
std::shared_ptr<Texture> GetPlaceholderTexture() const;
|
||||
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> GetUnlitPipeline(
|
||||
SceneContextOptions opts) const {
|
||||
return GetPipeline(unlit_pipeline_, opts);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Context> context_;
|
||||
|
||||
template <class T>
|
||||
using Variants = std::unordered_map<SceneContextOptions,
|
||||
std::unique_ptr<T>,
|
||||
SceneContextOptions::Hash,
|
||||
SceneContextOptions::Equal>;
|
||||
|
||||
mutable Variants<UnlitPipeline> unlit_pipeline_;
|
||||
|
||||
template <class TypedPipeline>
|
||||
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
|
||||
Variants<TypedPipeline>& container,
|
||||
@@ -91,7 +90,13 @@ class SceneContext {
|
||||
return variant_pipeline;
|
||||
}
|
||||
|
||||
std::shared_ptr<Context> context_;
|
||||
mutable Variants<UnlitPipeline> unlit_pipeline_;
|
||||
|
||||
bool is_valid_ = false;
|
||||
// A 1x1 opaque white texture that can be used as a placeholder binding.
|
||||
// Available for the lifetime of the scene context
|
||||
std::shared_ptr<Texture> placeholder_texture_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(SceneContext);
|
||||
};
|
||||
|
||||
@@ -4,24 +4,71 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
#include "fml/logging.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "impeller/renderer/command.h"
|
||||
#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 {
|
||||
|
||||
SceneEncoder::SceneEncoder() = default;
|
||||
|
||||
void SceneEncoder::Add(const SceneCommand& command) {
|
||||
// TODO(bdero): Manage multi-pass translucency ordering.
|
||||
commands_.push_back(command);
|
||||
}
|
||||
|
||||
static void EncodeCommand(const SceneContext& scene_context,
|
||||
RenderPass& render_pass,
|
||||
const SceneCommand& scene_command) {
|
||||
auto& host_buffer = render_pass.GetTransientsBuffer();
|
||||
|
||||
Command cmd;
|
||||
cmd.label = scene_command.label;
|
||||
cmd.stencil_reference =
|
||||
0; // TODO(bdero): Configurable stencil ref per-command.
|
||||
|
||||
cmd.BindVertices(scene_command.geometry->GetVertexBuffer(
|
||||
*scene_context.GetContext()->GetResourceAllocator()));
|
||||
|
||||
cmd.pipeline =
|
||||
scene_command.material->GetPipeline(scene_context, render_pass);
|
||||
scene_command.material->BindToCommand(scene_context, host_buffer, cmd);
|
||||
|
||||
GeometryVertexShader::VertInfo info;
|
||||
info.mvp = scene_command.transform;
|
||||
GeometryVertexShader::BindVertInfo(cmd, host_buffer.EmplaceUniform(info));
|
||||
|
||||
render_pass.AddCommand(std::move(cmd));
|
||||
}
|
||||
|
||||
std::shared_ptr<CommandBuffer> SceneEncoder::BuildSceneCommandBuffer(
|
||||
Context& context,
|
||||
const SceneContext& scene_context,
|
||||
const RenderTarget& render_target) const {
|
||||
auto command_buffer = context.CreateCommandBuffer();
|
||||
auto command_buffer = scene_context.GetContext()->CreateCommandBuffer();
|
||||
if (!command_buffer) {
|
||||
FML_LOG(ERROR) << "Failed to create command buffer.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto render_pass = command_buffer->CreateRenderPass(render_target);
|
||||
if (!render_pass) {
|
||||
FML_LOG(ERROR) << "Failed to create render pass.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto& command : commands_) {
|
||||
EncodeCommand(scene_context, *render_pass, command);
|
||||
}
|
||||
|
||||
if (!render_pass->EncodeCommands()) {
|
||||
FML_LOG(ERROR) << "Failed to encode render pass commands.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return command_buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,24 +5,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
#include "impeller/renderer/command_buffer.h"
|
||||
#include "impeller/scene/geometry.h"
|
||||
#include "impeller/scene/material.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace scene {
|
||||
|
||||
class Scene;
|
||||
|
||||
struct SceneCommand {
|
||||
std::string label;
|
||||
Matrix transform;
|
||||
Geometry* geometry;
|
||||
Material* material;
|
||||
};
|
||||
|
||||
class SceneEncoder {
|
||||
public:
|
||||
void Add(const SceneCommand& command);
|
||||
|
||||
private:
|
||||
SceneEncoder();
|
||||
|
||||
std::shared_ptr<CommandBuffer> BuildSceneCommandBuffer(
|
||||
Context& context,
|
||||
const SceneContext& scene_context,
|
||||
const RenderTarget& render_target) const;
|
||||
|
||||
std::vector<SceneCommand> commands_;
|
||||
|
||||
friend Scene;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(SceneEncoder);
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/scene/static_mesh_entity.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "impeller/scene/material.h"
|
||||
#include "impeller/scene/scene_encoder.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace scene {
|
||||
@@ -23,6 +26,13 @@ void StaticMeshEntity::SetMaterial(std::shared_ptr<Material> material) {
|
||||
// |SceneEntity|
|
||||
bool StaticMeshEntity::OnRender(SceneEncoder& encoder,
|
||||
const Camera& camera) const {
|
||||
SceneCommand command = {
|
||||
.label = "Static Mesh",
|
||||
.transform = GetGlobalTransform(),
|
||||
.geometry = geometry_.get(),
|
||||
.material = material_.get(),
|
||||
};
|
||||
encoder.Add(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user