blob: 949decaa40771207933de4a5b7b364246f122c51 [file] [log] [blame]
// Copyright 2020 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef IREE_HAL_VULKAN_SERIALIZING_COMMAND_QUEUE_H_
#define IREE_HAL_VULKAN_SERIALIZING_COMMAND_QUEUE_H_
// clang-format off: must be included before all other headers.
#include "iree/hal/vulkan/vulkan_headers.h"
// clang-format on
#include <stddef.h>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "iree/base/api.h"
#include "iree/base/internal/synchronization.h"
#include "iree/hal/api.h"
#include "iree/hal/vulkan/command_queue.h"
#include "iree/hal/vulkan/dynamic_symbols.h"
#include "iree/hal/vulkan/handle_util.h"
#include "iree/hal/vulkan/timepoint_util.h"
#include "iree/hal/vulkan/util/intrusive_list.h"
#include "iree/hal/vulkan/util/ref_ptr.h"
namespace iree {
namespace hal {
namespace vulkan {
using SemaphoreValue = std::pair<iree_hal_semaphore_t*, uint64_t>;
// A command queue that potentially defers and serializes command buffer
// submission to the GPU.
//
// This command queue is designed to be used together with emulated timeline
// semaphores. Timeline semaphores can follow wait-before-signal submission
// order but binary `VkSemaphore` cannot. So when emulating timeline semaphores
// with binary `VkSemaphore`s and `VkFence`s, we need to make sure no
// wait-before-signal submission order occur for binary `VkSemaphore`s. The way
// to enforce that is to defer the submission until we can be certain that the
// `VkSemaphore`s emulating time points in the timeline are all *submitted* to
// the GPU.
class SerializingCommandQueue final : public CommandQueue {
public:
SerializingCommandQueue(VkDeviceHandle* logical_device,
iree_hal_command_category_t supported_categories,
VkQueue queue, TimePointFencePool* fence_pool);
~SerializingCommandQueue() override;
const ref_ptr<DynamicSymbols>& syms() const {
return logical_device_->syms();
}
iree_status_t Submit(iree_host_size_t batch_count,
const iree_hal_submission_batch_t* batches) override;
iree_status_t WaitIdle(iree_timeout_t timeout) override;
// Releases all deferred submissions ready to submit to the GPU.
iree_status_t AdvanceQueueSubmission();
// Aborts all deferred submissions and waits for submitted work to complete.
void AbortQueueSubmission();
// Informs this queue that the given |fences| are known to have signaled.
void SignalFences(const std::vector<VkFence>& fences);
private:
// A submission batch together with the fence to singal its status.
struct FencedSubmission : public IntrusiveLinkBase<void> {
std::vector<SemaphoreValue> wait_semaphores;
std::vector<VkCommandBuffer> command_buffers;
std::vector<SemaphoreValue> signal_semaphores;
ref_ptr<TimePointFence> fence;
};
// Processes deferred submissions in this queue and returns whether there are
// new workload submitted to the GPU if no errors happen.
iree_status_t ProcessDeferredSubmissions(bool* out_work_submitted = NULL);
iree_status_t TryProcessDeferredSubmissions(
IntrusiveList<std::unique_ptr<FencedSubmission>>& remaining_submissions,
bool* out_work_submitted);
TimePointFencePool* fence_pool_;
// A list of fences that are submitted to GPU.
std::vector<ref_ptr<TimePointFence>> pending_fences_ IREE_GUARDED_BY(mutex_);
// A list of deferred submissions that haven't been submitted to GPU.
IntrusiveList<std::unique_ptr<FencedSubmission>> deferred_submissions_
IREE_GUARDED_BY(mutex_);
};
} // namespace vulkan
} // namespace hal
} // namespace iree
#endif // IREE_HAL_VULKAN_SERIALIZING_COMMAND_QUEUE_H_