blob: f41e0e337c18098d41fcda68ca2f40656ae97b65 [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.
#pragma once
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/formats.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->SetDescriptorSetLayouts(
VertexShader::kDescriptorSetLayouts)) {
VALIDATION_LOG << "Cound not configure vertex descriptor set layout for"
" pipeline named '"
<< VertexShader::kLabel << "'.";
return false;
}
if (!vertex_descriptor->SetDescriptorSetLayouts(
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.GetColorAttachmentPixelFormat();
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(PixelFormat::kDefaultStencil);
}
return true;
}
};
} // namespace impeller