| // 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 |