1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_VULKAN_VULKAN_COMMAND_BUFFER_H_
#define GPU_VULKAN_VULKAN_COMMAND_BUFFER_H_
#include <vulkan/vulkan_core.h>
#include "base/check.h"
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "gpu/vulkan/vulkan_fence_helper.h"
namespace gpu {
class VulkanCommandPool;
class VulkanDeviceQueue;
class COMPONENT_EXPORT(VULKAN) VulkanCommandBuffer {
public:
VulkanCommandBuffer(VulkanDeviceQueue* device_queue,
VulkanCommandPool* command_pool,
bool primary);
VulkanCommandBuffer(const VulkanCommandBuffer&) = delete;
VulkanCommandBuffer& operator=(const VulkanCommandBuffer&) = delete;
~VulkanCommandBuffer();
bool Initialize();
// Destroy() should be called when all related GPU tasks have been finished.
void Destroy();
// Submit primary command buffer to the queue.
bool Submit(uint32_t num_wait_semaphores,
VkSemaphore* wait_semaphores,
uint32_t num_signal_semaphores,
VkSemaphore* signal_semaphores,
bool allow_protected_memory = false);
// Enqueue secondary command buffer within a primary command buffer.
void Enqueue(VkCommandBuffer primary_command_buffer);
void Clear();
// This blocks until the commands from the previous submit are done.
void Wait(uint64_t timeout);
// This simply tests asynchronously if the commands from the previous submit
// is finished.
bool SubmissionFinished();
void TransitionImageLayout(
VkImage image,
VkImageLayout old_layout,
VkImageLayout new_layout,
uint32_t src_queue_family_index = VK_QUEUE_FAMILY_IGNORED,
uint32_t dst_queue_family_index = VK_QUEUE_FAMILY_IGNORED);
void CopyBufferToImage(VkBuffer buffer,
VkImage image,
uint32_t buffer_width,
uint32_t buffer_height,
uint32_t width,
uint32_t height,
uint64_t buffer_offset = 0);
void CopyImageToBuffer(VkBuffer buffer,
VkImage image,
uint32_t buffer_width,
uint32_t buffer_height,
uint32_t width,
uint32_t height,
uint64_t buffer_offset = 0);
private:
friend class CommandBufferRecorderBase;
enum RecordType {
// Nothing has been recorded yet.
RECORD_TYPE_EMPTY,
// Recorded for single use, will be reset upon submission.
RECORD_TYPE_SINGLE_USE,
// Recording for multi use, once submitted it can't be modified until reset.
RECORD_TYPE_MULTI_USE,
// Recorded for multi-use, can no longer be modified unless reset.
RECORD_TYPE_RECORDED,
// Dirty, should be cleared before use. This assumes its externally
// synchronized and the command buffer is no longer in use.
RECORD_TYPE_DIRTY,
};
void PostExecution();
void ResetIfDirty();
const bool primary_;
bool recording_ = false;
RecordType record_type_ = RECORD_TYPE_EMPTY;
raw_ptr<VulkanDeviceQueue> device_queue_;
raw_ptr<VulkanCommandPool> command_pool_;
VkCommandBuffer command_buffer_ = VK_NULL_HANDLE;
VulkanFenceHelper::FenceHandle submission_fence_;
};
class COMPONENT_EXPORT(VULKAN) CommandBufferRecorderBase {
public:
VkCommandBuffer handle() const { return handle_; }
protected:
CommandBufferRecorderBase(VulkanCommandBuffer& command_buffer)
: handle_(command_buffer.command_buffer_) {
command_buffer.ResetIfDirty();
}
virtual ~CommandBufferRecorderBase();
void ValidateSingleUse(VulkanCommandBuffer& command_buffer) {
DCHECK((VulkanCommandBuffer::RECORD_TYPE_SINGLE_USE ==
command_buffer.record_type_) ||
(VulkanCommandBuffer::RECORD_TYPE_EMPTY ==
command_buffer.record_type_));
command_buffer.record_type_ = VulkanCommandBuffer::RECORD_TYPE_SINGLE_USE;
}
void ValidateMultiUse(VulkanCommandBuffer& command_buffer) {
DCHECK((VulkanCommandBuffer::RECORD_TYPE_MULTI_USE ==
command_buffer.record_type_) ||
(VulkanCommandBuffer::RECORD_TYPE_EMPTY ==
command_buffer.record_type_));
command_buffer.record_type_ = VulkanCommandBuffer::RECORD_TYPE_MULTI_USE;
}
VkCommandBuffer handle_;
};
class COMPONENT_EXPORT(VULKAN) ScopedMultiUseCommandBufferRecorder
: public CommandBufferRecorderBase {
public:
ScopedMultiUseCommandBufferRecorder(VulkanCommandBuffer& command_buffer);
ScopedMultiUseCommandBufferRecorder(
const ScopedMultiUseCommandBufferRecorder&) = delete;
ScopedMultiUseCommandBufferRecorder& operator=(
const ScopedMultiUseCommandBufferRecorder&) = delete;
~ScopedMultiUseCommandBufferRecorder() override {}
};
class COMPONENT_EXPORT(VULKAN) ScopedSingleUseCommandBufferRecorder
: public CommandBufferRecorderBase {
public:
ScopedSingleUseCommandBufferRecorder(VulkanCommandBuffer& command_buffer);
ScopedSingleUseCommandBufferRecorder(
const ScopedSingleUseCommandBufferRecorder&) = delete;
ScopedSingleUseCommandBufferRecorder& operator=(
const ScopedSingleUseCommandBufferRecorder&) = delete;
~ScopedSingleUseCommandBufferRecorder() override {}
};
} // namespace gpu
#endif // GPU_VULKAN_VULKAN_COMMAND_BUFFER_H_
|