| // 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. | |
| #ifndef FLUTTER_IMPELLER_RENDERER_PIPELINE_BUILDER_H_ | |
| #define FLUTTER_IMPELLER_RENDERER_PIPELINE_BUILDER_H_ | |
| #include "flutter/fml/logging.h" | |
| #include "flutter/fml/macros.h" | |
| #include "impeller/base/strings.h" | |
| #include "impeller/base/validation.h" | |
| #include "impeller/core/formats.h" | |
| #include "impeller/renderer/context.h" | |
| #include "impeller/renderer/pipeline_descriptor.h" | |
| #include "impeller/renderer/shader_library.h" | |
| #include "impeller/renderer/vertex_descriptor.h" | |
| namespace impeller { | |
| //------------------------------------------------------------------------------ | |
| /// @brief An optional (but highly recommended) utility for creating | |
| /// pipelines from reflected shader information. | |
| /// | |
| /// @tparam VertexShader_ The reflected vertex shader information. Found | |
| /// in a generated header file called | |
| /// <shader_name>.vert.h. | |
| /// @tparam FragmentShader_ The reflected fragment shader information. | |
| /// Found in a generated header file called | |
| /// <shader_name>.frag.h. | |
| /// | |
| template <class VertexShader_, class FragmentShader_> | |
| struct PipelineBuilder { | |
| public: | |
| using VertexShader = VertexShader_; | |
| using FragmentShader = FragmentShader_; | |
| static constexpr size_t kVertexBufferIndex = | |
| VertexDescriptor::kReservedVertexBufferIndex; | |
| //---------------------------------------------------------------------------- | |
| /// @brief Create a default pipeline descriptor using the combination | |
| /// reflected shader information. The descriptor can be configured | |
| /// further before a pipeline state object is created using it. | |
| /// | |
| /// @param[in] context The context | |
| /// | |
| /// @return If the combination of reflected shader information is | |
| /// compatible and the requisite functions can be found in the | |
| /// context, a pipeline descriptor. | |
| /// | |
| static std::optional<PipelineDescriptor> MakeDefaultPipelineDescriptor( | |
| const Context& context, | |
| const std::vector<Scalar>& constants = {}) { | |
| PipelineDescriptor desc; | |
| desc.SetSpecializationConstants(constants); | |
| if (InitializePipelineDescriptorDefaults(context, desc)) { | |
| return {std::move(desc)}; | |
| } | |
| return std::nullopt; | |
| } | |
| [[nodiscard]] static bool InitializePipelineDescriptorDefaults( | |
| const Context& context, | |
| PipelineDescriptor& desc) { | |
| // Setup debug instrumentation. | |
| desc.SetLabel(SPrintF("%s Pipeline", FragmentShader::kLabel.data())); | |
| // Resolve pipeline entrypoints. | |
| { | |
| auto vertex_function = context.GetShaderLibrary()->GetFunction( | |
| VertexShader::kEntrypointName, ShaderStage::kVertex); | |
| auto fragment_function = context.GetShaderLibrary()->GetFunction( | |
| FragmentShader::kEntrypointName, ShaderStage::kFragment); | |
| if (!vertex_function || !fragment_function) { | |
| VALIDATION_LOG << "Could not resolve pipeline entrypoint(s) '" | |
| << VertexShader::kEntrypointName << "' and '" | |
| << FragmentShader::kEntrypointName | |
| << "' for pipeline named '" << VertexShader::kLabel | |
| << "'."; | |
| return false; | |
| } | |
| desc.AddStageEntrypoint(std::move(vertex_function)); | |
| desc.AddStageEntrypoint(std::move(fragment_function)); | |
| } | |
| // Setup the vertex descriptor from reflected information. | |
| { | |
| auto vertex_descriptor = std::make_shared<VertexDescriptor>(); | |
| vertex_descriptor->SetStageInputs(VertexShader::kAllShaderStageInputs, | |
| VertexShader::kInterleavedBufferLayout); | |
| vertex_descriptor->RegisterDescriptorSetLayouts( | |
| VertexShader::kDescriptorSetLayouts); | |
| vertex_descriptor->RegisterDescriptorSetLayouts( | |
| FragmentShader::kDescriptorSetLayouts); | |
| desc.SetVertexDescriptor(std::move(vertex_descriptor)); | |
| } | |
| // Setup fragment shader output descriptions. | |
| { | |
| // Configure the sole color attachments pixel format. This is by | |
| // convention. | |
| ColorAttachmentDescriptor color0; | |
| color0.format = context.GetCapabilities()->GetDefaultColorFormat(); | |
| color0.blending_enabled = true; | |
| desc.SetColorAttachmentDescriptor(0u, color0); | |
| } | |
| // Setup default depth buffer descriptions. | |
| { | |
| DepthAttachmentDescriptor depth0; | |
| depth0.depth_compare = CompareFunction::kAlways; | |
| desc.SetDepthStencilAttachmentDescriptor(depth0); | |
| desc.SetDepthPixelFormat( | |
| context.GetCapabilities()->GetDefaultDepthStencilFormat()); | |
| } | |
| // Setup default stencil buffer descriptions. | |
| { | |
| StencilAttachmentDescriptor stencil0; | |
| stencil0.stencil_compare = CompareFunction::kEqual; | |
| desc.SetStencilAttachmentDescriptors(stencil0); | |
| desc.SetStencilPixelFormat( | |
| context.GetCapabilities()->GetDefaultDepthStencilFormat()); | |
| } | |
| return true; | |
| } | |
| }; | |
| } // namespace impeller | |
| #endif // FLUTTER_IMPELLER_RENDERER_PIPELINE_BUILDER_H_ |