#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();
void Destroy();
bool Submit(uint32_t num_wait_semaphores,
VkSemaphore* wait_semaphores,
uint32_t num_signal_semaphores,
VkSemaphore* signal_semaphores,
bool allow_protected_memory = false);
void Enqueue(VkCommandBuffer primary_command_buffer);
void Clear();
void Wait(uint64_t timeout);
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 {
RECORD_TYPE_EMPTY,
RECORD_TYPE_SINGLE_USE,
RECORD_TYPE_MULTI_USE,
RECORD_TYPE_RECORDED,
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 {}
};
}
#endif