blob: 16be034562d69331c61454f28518853dc62c9f9e [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 <future>
#include "flutter/fml/macros.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/pipeline_builder.h"
namespace impeller {
class PipelineLibrary;
class Pipeline;
// TODO(csg): Using a simple future is sub-optimal since callers that want to
// eagerly create and cache pipeline variants will have to await on the future
// to get its pipeline descriptor (unless they have explicitly cached it). This
// would be a concurrency pessimization.
//
// Use a struct that stores the future and the descriptor separately.
using PipelineFuture = std::shared_future<std::shared_ptr<Pipeline>>;
//------------------------------------------------------------------------------
/// @brief Describes the fixed function and programmable aspects of
/// rendering and compute operations performed by commands submitted
/// to the GPU via a command buffer.
///
/// A pipeline handle must be allocated upfront and kept alive for
/// as long as possible. Do not create a pipeline object within a
/// frame workload.
///
/// This pipeline object is almost never used directly as it is
/// untyped. Use reflected shader information generated by the
/// Impeller offline shader compiler to generate a typed pipeline
/// object.
///
class Pipeline {
public:
virtual ~Pipeline();
virtual bool IsValid() const = 0;
//----------------------------------------------------------------------------
/// @brief Get the descriptor that was responsible for creating this
/// pipeline. It may be copied and modified to create a pipeline
/// variant.
///
/// @return The descriptor.
///
const PipelineDescriptor& GetDescriptor() const;
PipelineFuture CreateVariant(
std::function<void(PipelineDescriptor& desc)> descriptor_callback) const;
protected:
Pipeline(std::weak_ptr<PipelineLibrary> library, PipelineDescriptor desc);
private:
const std::weak_ptr<PipelineLibrary> library_;
const PipelineDescriptor desc_;
FML_DISALLOW_COPY_AND_ASSIGN(Pipeline);
};
PipelineFuture CreatePipelineFuture(const Context& context,
std::optional<PipelineDescriptor> desc);
template <class VertexShader_, class FragmentShader_>
class PipelineT {
public:
using VertexShader = VertexShader_;
using FragmentShader = FragmentShader_;
using Builder = PipelineBuilder<VertexShader, FragmentShader>;
explicit PipelineT(const Context& context)
: PipelineT(CreatePipelineFuture(
context,
Builder::MakeDefaultPipelineDescriptor(context))) {}
explicit PipelineT(const Context& context,
std::optional<PipelineDescriptor> desc)
: PipelineT(CreatePipelineFuture(context, desc)) {}
explicit PipelineT(PipelineFuture future)
: pipeline_future_(std::move(future)) {}
std::shared_ptr<Pipeline> WaitAndGet() {
if (did_wait_) {
return pipeline_;
}
did_wait_ = true;
if (pipeline_future_.valid()) {
pipeline_ = pipeline_future_.get();
}
return pipeline_;
}
private:
PipelineFuture pipeline_future_;
std::shared_ptr<Pipeline> pipeline_;
bool did_wait_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(PipelineT);
};
} // namespace impeller