| // 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. |
| |
| #pragma once |
| |
| #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) { |
| PipelineDescriptor desc; |
| if (InitializePipelineDescriptorDefaults(context, desc)) { |
| return {std::move(desc)}; |
| } else { |
| 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>(); |
| if (!vertex_descriptor->SetStageInputs( |
| VertexShader::kAllShaderStageInputs)) { |
| VALIDATION_LOG |
| << "Could not configure vertex descriptor for pipeline named '" |
| << VertexShader::kLabel << "'."; |
| return false; |
| } |
| if (!vertex_descriptor->RegisterDescriptorSetLayouts( |
| VertexShader::kDescriptorSetLayouts)) { |
| VALIDATION_LOG << "Cound not configure vertex descriptor set layout for" |
| " pipeline named '" |
| << VertexShader::kLabel << "'."; |
| return false; |
| } |
| |
| if (!vertex_descriptor->RegisterDescriptorSetLayouts( |
| FragmentShader::kDescriptorSetLayouts)) { |
| VALIDATION_LOG << "Cound not configure vertex descriptor set layout for" |
| " pipeline named '" |
| << VertexShader::kLabel << "'."; |
| return false; |
| } |
| |
| 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 stencil buffer descriptions. |
| { |
| StencilAttachmentDescriptor stencil0; |
| stencil0.stencil_compare = CompareFunction::kEqual; |
| desc.SetStencilAttachmentDescriptors(stencil0); |
| desc.SetStencilPixelFormat( |
| context.GetCapabilities()->GetDefaultStencilFormat()); |
| } |
| |
| return true; |
| } |
| }; |
| |
| } // namespace impeller |