blob: f8884a02b803df9fb45a4da466fa6e06a9203d3c [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 SRC_UI_LIB_ESCHER_VK_CHAINED_SEMAPHORE_GENERATOR_H_
#define SRC_UI_LIB_ESCHER_VK_CHAINED_SEMAPHORE_GENERATOR_H_
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/ui/lib/escher/renderer/semaphore.h"
#include <vulkan/vulkan.hpp>
namespace escher {
// Forward declaration.
class ChainedSemaphoreGenerator;
using ChainedSemaphoreGeneratorWeakPtr = fxl::WeakPtr<ChainedSemaphoreGenerator>;
// ChainedSemaphoreGenerator is used for generating VkSemaphores for
// synchronizing between gfx::Engine, gfx::Screenshotter, and gfx::Snaphshotter.
//
// Each time the caller calls TakeLastAndCreateNextSemaphore() to get a pair of
// VkSemaphore, which it will wait on |semaphore_to_wait| before executing
// its command and signal |semaphore_to_signal| after finishing execution. When
// the next caller calls this function, the caller will wait on the semaphore
// signalled by the previous caller. In this way all components are chained
// together and we can ensure the execution sequence of command buffers.
//
// Therefore, the caller MUST always signal |semaphore_to_signal| in their
// command buffer, otherwise the next caller will wait on this semaphore
// forever.
//
// Also, the caller MUST ensure that the submission sequence MUST be of the
// same order of the semaphore chain, otherwise it will cause deadlock on most
// platforms.
//
// TODO(fxbug.dev/41980): Add integration tests to test synchronization of gfx Engine,
// Screenshotter and Snapshotter as well.
//
class ChainedSemaphoreGenerator {
public:
struct SemaphorePair {
// The |semaphore_to_wait| was the last semaphore generated by this class.
SemaphorePtr semaphore_to_wait;
// The |semaphore_to_signal| signal will be waited on by its next caller.
SemaphorePtr semaphore_to_signal;
};
ChainedSemaphoreGenerator(vk::Device device);
SemaphorePair TakeLastAndCreateNextSemaphore(bool exportable = false) {
return SemaphorePair{.semaphore_to_wait = TakeLastSemaphore(),
.semaphore_to_signal = CreateNextSemaphore(exportable)};
}
ChainedSemaphoreGeneratorWeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
private:
SemaphorePtr CreateNextSemaphore(bool exportable);
SemaphorePtr TakeLastSemaphore();
vk::Device device_;
SemaphorePtr last_semaphore_ = nullptr;
fxl::WeakPtrFactory<ChainedSemaphoreGenerator> weak_factory_; // must be last
};
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_VK_CHAINED_SEMAPHORE_GENERATOR_H_