提交 fc8b9777 编写于 作者: C Chinmay Garde 提交者: GitHub

Pipelines vend single use continuations that callers can complete at any time...

Pipelines vend single use continuations that callers can complete at any time to signal readiness of a pipeline resource. (#2957)
上级 32ba8596
...@@ -43,24 +43,35 @@ void Animator::Start() { ...@@ -43,24 +43,35 @@ void Animator::Start() {
void Animator::BeginFrame(int64_t time_stamp) { void Animator::BeginFrame(int64_t time_stamp) {
pending_frame_semaphore_.Signal(); pending_frame_semaphore_.Signal();
LayerTreePipeline::Producer producer = [this]() { if (!producer_continuation_) {
renderable_tree_.reset(); // We may already have a valid pipeline continuation in case a previous
ftl::Stopwatch stopwatch; // begin frame did not result in an Animation::Render. Simply reuse that
stopwatch.Start(); // instead of asking the pipeline for a fresh continuation.
engine_->BeginFrame(ftl::TimePoint::Now()); producer_continuation_ = layer_tree_pipeline_->Produce();
if (renderable_tree_) {
renderable_tree_->set_construction_time(stopwatch.Elapsed()); if (!producer_continuation_) {
// If we still don't have valid continuation, the pipeline is currently
// full because the consumer is being too slow. Try again at the next
// frame interval.
TRACE_EVENT_INSTANT0("flutter", "ConsumerSlowDefer",
TRACE_EVENT_SCOPE_PROCESS);
RequestFrame();
return;
} }
return std::move(renderable_tree_);
};
if (!layer_tree_pipeline_->Produce(producer)) {
TRACE_EVENT_INSTANT0("flutter", "ConsumerSlowDefer",
TRACE_EVENT_SCOPE_PROCESS);
RequestFrame();
return;
} }
// We have acquired a valid continuation from the pipeline and are ready
// to service potential frame.
DCHECK(producer_continuation_);
engine_->BeginFrame(ftl::TimePoint::Now());
}
void Animator::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
// Commit the pending continuation.
producer_continuation_.Complete(std::move(layer_tree));
// Notify the rasterizer that the pipeline has items it may consume.
auto weak_rasterizer = rasterizer_->GetWeakRasterizerPtr(); auto weak_rasterizer = rasterizer_->GetWeakRasterizerPtr();
auto pipeline = layer_tree_pipeline_; auto pipeline = layer_tree_pipeline_;
...@@ -72,10 +83,6 @@ void Animator::BeginFrame(int64_t time_stamp) { ...@@ -72,10 +83,6 @@ void Animator::BeginFrame(int64_t time_stamp) {
}); });
} }
void Animator::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
renderable_tree_ = std::move(layer_tree);
}
void Animator::RequestFrame() { void Animator::RequestFrame() {
if (paused_) { if (paused_) {
return; return;
......
...@@ -47,7 +47,7 @@ class Animator { ...@@ -47,7 +47,7 @@ class Animator {
vsync::VSyncProviderPtr fallback_vsync_provider_; vsync::VSyncProviderPtr fallback_vsync_provider_;
ftl::RefPtr<LayerTreePipeline> layer_tree_pipeline_; ftl::RefPtr<LayerTreePipeline> layer_tree_pipeline_;
flutter::Semaphore pending_frame_semaphore_; flutter::Semaphore pending_frame_semaphore_;
std::unique_ptr<flow::LayerTree> renderable_tree_; LayerTreePipeline::ProducerContinuation producer_continuation_;
bool paused_; bool paused_;
base::WeakPtrFactory<Animator> weak_factory_; base::WeakPtrFactory<Animator> weak_factory_;
......
...@@ -3,9 +3,3 @@ ...@@ -3,9 +3,3 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "flutter/synchronization/pipeline.h" #include "flutter/synchronization/pipeline.h"
namespace flutter {
//
} // namespace flutter
...@@ -30,39 +30,60 @@ class Pipeline : public ftl::RefCountedThreadSafe<Pipeline<R>> { ...@@ -30,39 +30,60 @@ class Pipeline : public ftl::RefCountedThreadSafe<Pipeline<R>> {
using Resource = R; using Resource = R;
using ResourcePtr = std::unique_ptr<Resource>; using ResourcePtr = std::unique_ptr<Resource>;
explicit Pipeline(uint32_t depth) : empty_(depth), available_(0) {} /// Denotes a spot in the pipeline reserved for the producer to finish
/// preparing a completed pipeline resource.
~Pipeline() {} class ProducerContinuation {
public:
bool IsValid() const { return empty_.IsValid() && available_.IsValid(); } ProducerContinuation() = default;
ProducerContinuation(ProducerContinuation&& other)
: continuation_(other.continuation_) {
other.continuation_ = nullptr;
}
using Producer = std::function<ResourcePtr(void)>; ProducerContinuation& operator=(ProducerContinuation&& other) {
std::swap(continuation_, other.continuation_);
return *this;
}
FTL_WARN_UNUSED_RESULT ~ProducerContinuation() {
bool Produce(Producer producer) { if (continuation_) {
if (producer == nullptr) { continuation_(nullptr);
return false; }
} }
if (!empty_.TryWait()) { void Complete(ResourcePtr resource) {
return false; if (continuation_) {
continuation_(std::move(resource));
continuation_ = nullptr;
}
} }
ResourcePtr resource; operator bool() const { return continuation_ != nullptr; }
{ private:
TRACE_EVENT0("flutter", "PipelineProduce"); friend class Pipeline;
resource = producer();
}
{ std::function<void(ResourcePtr)> continuation_;
ftl::MutexLocker lock(&queue_mutex_);
queue_.emplace(std::move(resource));
}
available_.Signal(); ProducerContinuation(std::function<void(ResourcePtr)> continuation)
: continuation_(continuation) {}
FTL_DISALLOW_COPY_AND_ASSIGN(ProducerContinuation);
};
return true; explicit Pipeline(uint32_t depth) : empty_(depth), available_(0) {}
~Pipeline() = default;
bool IsValid() const { return empty_.IsValid() && available_.IsValid(); }
ProducerContinuation Produce() {
if (!empty_.TryWait()) {
return {};
}
return {std::bind(&Pipeline::ProducerCommit, this, std::placeholders::_1)};
} }
using Consumer = std::function<void(ResourcePtr)>; using Consumer = std::function<void(ResourcePtr)>;
...@@ -104,6 +125,16 @@ class Pipeline : public ftl::RefCountedThreadSafe<Pipeline<R>> { ...@@ -104,6 +125,16 @@ class Pipeline : public ftl::RefCountedThreadSafe<Pipeline<R>> {
ftl::Mutex queue_mutex_; ftl::Mutex queue_mutex_;
std::queue<ResourcePtr> queue_; std::queue<ResourcePtr> queue_;
void ProducerCommit(ResourcePtr resource) {
{
ftl::MutexLocker lock(&queue_mutex_);
queue_.emplace(std::move(resource));
}
// Ensure the queue mutex is not held as that would be a pessimization.
available_.Signal();
}
FTL_DISALLOW_COPY_AND_ASSIGN(Pipeline); FTL_DISALLOW_COPY_AND_ASSIGN(Pipeline);
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册