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

gpu / vulkan / vulkan_command_buffer.h [blame]

// 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_