|  | // 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 = render_pass.GetTransientsBuffer(); | 
|  |  | 
|  | Command cmd; | 
|  | DEBUG_COMMAND_INFO(cmd, scene_command.label); | 
|  | cmd.stencil_reference = | 
|  | 0;  // TODO(bdero): Configurable stencil ref per-command. | 
|  |  | 
|  | cmd.pipeline = 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, | 
|  | cmd); | 
|  | scene_command.material->BindToCommand(scene_context, host_buffer, cmd); | 
|  |  | 
|  | render_pass.AddCommand(std::move(cmd)); | 
|  | } | 
|  |  | 
|  | 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 |