blob: 9f934f39e4feebe227251c86e34f41bfe9c99bc7 [file] [log] [blame]
// 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.
#include "flutter/fml/macros.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"
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,
const Matrix& view_transform,
RenderPass& render_pass,
const SceneCommand& scene_command) {
auto& host_buffer = scene_context.GetTransientsBuffer();
render_pass.SetCommandLabel(scene_command.label);
// TODO(bdero): Configurable stencil ref per-command.
render_pass.SetStencilReference(0);
render_pass.SetPipeline(scene_context.GetPipeline(
PipelineKey{scene_command.geometry->GetGeometryType(),
scene_command.material->GetMaterialType()},
scene_command.material->GetContextOptions(render_pass)));
scene_command.geometry->BindToCommand(
scene_context, host_buffer, view_transform * scene_command.transform,
render_pass);
scene_command.material->BindToCommand(scene_context, host_buffer,
render_pass);
render_pass.Draw();
;
}
std::shared_ptr<CommandBuffer> SceneEncoder::BuildSceneCommandBuffer(
const SceneContext& scene_context,
const Matrix& camera_transform,
RenderTarget render_target) const {
{
TextureDescriptor ds_texture;
ds_texture.type = TextureType::kTexture2DMultisample;
ds_texture.format = PixelFormat::kD32FloatS8UInt;
ds_texture.size = render_target.GetRenderTargetSize();
ds_texture.usage =
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
ds_texture.sample_count = SampleCount::kCount4;
ds_texture.storage_mode = StorageMode::kDeviceTransient;
auto texture =
scene_context.GetContext()->GetResourceAllocator()->CreateTexture(
ds_texture);
DepthAttachment depth;
depth.load_action = LoadAction::kClear;
depth.store_action = StoreAction::kDontCare;
depth.clear_depth = 1.0;
depth.texture = texture;
render_target.SetDepthAttachment(depth);
// The stencil and depth buffers must be the same texture for MacOS ARM
// and Vulkan.
StencilAttachment stencil;
stencil.load_action = LoadAction::kClear;
stencil.store_action = StoreAction::kDontCare;
stencil.clear_stencil = 0u;
stencil.texture = texture;
render_target.SetStencilAttachment(stencil);
}
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, camera_transform, *render_pass, command);
}
if (!render_pass->EncodeCommands()) {
FML_LOG(ERROR) << "Failed to encode render pass commands.";
return nullptr;
}
return command_buffer;
}
} // namespace scene
} // namespace impeller