Add commandTestBase

Add a testbase class that prerecorded the command buffer which only
submits a single command buffer in its Run stage.

BUG=b:177290952
TEST=make

Change-Id: I902d33ad6d2976404a67bdb94127656aba83ef13
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vkbench/+/3161067
Tested-by: Po-Hsien Wang <pwang@chromium.org>
Auto-Submit: Po-Hsien Wang <pwang@chromium.org>
Commit-Queue: Po-Hsien Wang <pwang@chromium.org>
Reviewed-by: Chad Versace <chadversary@chromium.org>
diff --git a/src/main.cc b/src/main.cc
index ac98117..1941e24 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -206,7 +206,7 @@
   std::stable_sort(all_tests.begin(), all_tests.end(),
                    [](vkbench::testBase* a, vkbench::testBase* b) -> bool {
                      if (a->vk == b->vk) {
-                       return strcmp(a->Name(), b->Name()) < 0;
+                       return strcmp(a->Name().c_str(), b->Name().c_str()) < 0;
                      }
                      return a->vk < b->vk;
                    });
diff --git a/src/testBase.h b/src/testBase.h
index f098a49..b49ff47 100644
--- a/src/testBase.h
+++ b/src/testBase.h
@@ -7,6 +7,7 @@
 
 #include <vulkan/vulkan.hpp>
 
+#include <string>
 #include <vector>
 
 #include "src/filepath.h"
@@ -18,9 +19,9 @@
  public:
   virtual ~testBase() {}
   // Name of test.
-  virtual const char* Name() const = 0;
+  const std::string Name() const { return name_; }
   // Description of the test.
-  virtual const char* Desp() const = 0;
+  const std::string Desp() const { return desp_; }
   // Unit for formatted measurement.
   virtual const char* Unit() const = 0;
   // Given time elapse per iteration, format it into meaningful numbers.
@@ -47,6 +48,34 @@
   virtual void Destroy() = 0;
 
   vkbench::vkBase* vk;
+
+ protected:
+  std::string name_;
+  std::string desp_;
+};
+
+// commandTestBase submit a pre-recorded command buffers in its Run
+// method.
+class commandTestBase : public testBase {
+ public:
+  void Run() override { vk->SubmitAndWait(cmds_); }
+
+  void Destroy() override {
+    vk->GetDevice().freeCommandBuffers(vk->GetCommandPool(), cmds_);
+  }
+
+  // GetCommandBuffer returns a command buffer reference for submit later in Run
+  // Stage.
+  vk::CommandBuffer& GetCommandBuffer() {
+    if (cmds_.size() == 0) {
+      cmds_ = vk->GetDevice().allocateCommandBuffers(
+          {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
+    }
+    return cmds_[0];
+  }
+
+ private:
+  std::vector<vk::CommandBuffer> cmds_;
 };
 
 }  // namespace vkbench
diff --git a/src/tests/clear.cc b/src/tests/clear.cc
index e5a4a84..2f0c2df 100644
--- a/src/tests/clear.cc
+++ b/src/tests/clear.cc
@@ -50,9 +50,8 @@
   CreateRenderPass();
   CreateFrameBuffers();
 
-  cmds_ = vk->GetDevice().allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
-  cmds_[0].begin(vk::CommandBufferBeginInfo());
+  vk::CommandBuffer cmd = GetCommandBuffer();
+  cmd.begin(vk::CommandBufferBeginInfo());
   vk::RenderPassBeginInfo render_pass_info;
   render_pass_info.setFramebuffer(frame_buffer_)
       .setRenderPass(render_pass_)
@@ -60,24 +59,21 @@
       .setPClearValues(&clear_color_)
       .setRenderArea(vk::Rect2D({}, img_size_));
   for (uint32_t i = 0; i < CLEAR_CNT; i++) {
-    cmds_[0].beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
-    cmds_[0].endRenderPass();
+    cmd.beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
+    cmd.endRenderPass();
   }
-  cmds_[0].end();
-}
-
-void LoadOp::Run() {
-  vk->SubmitAndWait(cmds_);
+  cmd.end();
 }
 
 void LoadOp::Destroy() {
+  vkbench::commandTestBase::Destroy();
+
   vk::Device device = vk->GetDevice();
   device.destroyImageView(img_view_);
   delete img_;
 
   device.destroyFramebuffer(frame_buffer_);
   device.destroyRenderPass(render_pass_);
-  device.freeCommandBuffers(vk->GetCommandPool(), cmds_);
 }
 
 void LoadOp::CreateRenderPass() {
@@ -187,37 +183,26 @@
                                   vk::ImageUsageFlagBits::eTransferSrc,
                               vk::MemoryPropertyFlagBits::eDeviceLocal,
                               img_tiling_);
-  std::vector<vk::CommandBuffer> cmds = vk->GetDevice().allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
-  DEFER(vk->GetDevice().freeCommandBuffers(vk->GetCommandPool(), cmds));
-  cmds[0].begin(vk::CommandBufferBeginInfo());
-  img_->MoveLayout(cmds[0], vk::ImageLayout::eUndefined,
-                   vk::ImageLayout::eGeneral);
-  cmds[0].end();
-  vk->SubmitAndWait(cmds);
+  vk::CommandBuffer cmd = GetCommandBuffer();
+  cmd.begin(vk::CommandBufferBeginInfo());
+  img_->MoveLayout(cmd, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral);
+  cmd.end();
+  vk->SubmitAndWait(cmd);
 
-  cmds_ = device.allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
-  cmds_[0].begin(vk::CommandBufferBeginInfo());
+  cmd.begin(vk::CommandBufferBeginInfo());
   std::vector<vk::ImageSubresourceRange> subresource_range;
   subresource_range.push_back(
       vk::ImageSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}));
   for (uint32_t i = 0; i < CLEAR_CNT; i++) {
-    cmds_[0].clearColorImage(img_->GetImage(), vk::ImageLayout::eGeneral,
-                             clear_color_, subresource_range);
+    cmd.clearColorImage(img_->GetImage(), vk::ImageLayout::eGeneral,
+                        clear_color_, subresource_range);
   }
-  cmds_[0].end();
-}
-
-void CmdClearImage::Run() {
-  vk->SubmitAndWait(cmds_);
+  cmd.end();
 }
 
 void CmdClearImage::Destroy() {
-  vk::Device device = vk->GetDevice();
+  vkbench::commandTestBase::Destroy();
   delete img_;
-
-  device.freeCommandBuffers(vk->GetCommandPool(), cmds_);
 }
 
 Image CmdClearImage::GetImage() const {
diff --git a/src/tests/clear.h b/src/tests/clear.h
index 142365e..db3218a 100644
--- a/src/tests/clear.h
+++ b/src/tests/clear.h
@@ -14,7 +14,7 @@
 namespace vkbench {
 namespace clear {
 
-class LoadOp : public testBase {
+class LoadOp : public commandTestBase {
  public:
   LoadOp(vkBase* base,
          vk::Format format,
@@ -23,30 +23,22 @@
          std::string color);
   ~LoadOp() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "mpixels_sec"; }
   double FormatMeasurement(double time) override;
   Image GetImage() const override;
 
  protected:
   void Initialize() override;
-  void Run() override;
   void Destroy() override;
 
  private:
   void CreateRenderPass();
   void CreateFrameBuffers();
 
-  std::string name_;
-  std::string desp_;
   vk::Format img_format_;
   vk::ImageTiling img_tiling_;
   vk::Extent2D img_size_;
   vk::ClearValue clear_color_;
-
-  std::vector<vk::CommandBuffer> cmds_;
-
   vk::RenderPass render_pass_;
   vk::Framebuffer frame_buffer_;
   vkImage* img_;
@@ -55,7 +47,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoadOp);
 };
 
-class CmdClearImage : public testBase {
+class CmdClearImage : public commandTestBase {
  public:
   CmdClearImage(vkBase* base,
                 vk::Format format,
@@ -64,26 +56,19 @@
                 std::string color);
   ~CmdClearImage() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "mpixels_sec"; }
   double FormatMeasurement(double time) override;
   Image GetImage() const override;
 
  protected:
   void Initialize() override;
-  void Run() override;
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   vk::Format img_format_;
   vk::ImageTiling img_tiling_;
   vk::Extent2D img_size_;
   vk::ClearColorValue clear_color_;
-
-  std::vector<vk::CommandBuffer> cmds_;
   vkImage* img_;
 
   DISALLOW_COPY_AND_ASSIGN(CmdClearImage);
diff --git a/src/tests/copy.cc b/src/tests/copy.cc
index 8d7982b..26af81a 100644
--- a/src/tests/copy.cc
+++ b/src/tests/copy.cc
@@ -51,15 +51,13 @@
     RUNTIME_ERROR("Unsupported colors for copy test: {}", color_);
   }
 
-  std::vector<vk::CommandBuffer> cmds = vk->GetDevice().allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
-  DEFER(vk->GetDevice().freeCommandBuffers(vk->GetCommandPool(), cmds));
-  cmds[0].begin(vk::CommandBufferBeginInfo());
-  dest_img_->MoveLayout(cmds[0], vk::ImageLayout::ePreinitialized,
+  vk::CommandBuffer cmd = GetCommandBuffer();
+  cmd.begin(vk::CommandBufferBeginInfo());
+  dest_img_->MoveLayout(cmd, vk::ImageLayout::ePreinitialized,
                         vk::ImageLayout::eTransferDstOptimal);
-  temp_img->MoveLayout(cmds[0], vk::ImageLayout::ePreinitialized,
+  temp_img->MoveLayout(cmd, vk::ImageLayout::ePreinitialized,
                        vk::ImageLayout::eTransferSrcOptimal);
-  src_img_->MoveLayout(cmds[0], vk::ImageLayout::ePreinitialized,
+  src_img_->MoveLayout(cmd, vk::ImageLayout::ePreinitialized,
                        vk::ImageLayout::eTransferDstOptimal);
 
   // Copy the generated linear tiling image to our source image.
@@ -71,17 +69,15 @@
   copy_region.extent.setWidth(img_size_.width)
       .setHeight(img_size_.height)
       .setDepth(1);
-  cmds[0].copyImage(temp_img->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
-                    src_img_->GetImage(), vk::ImageLayout::eTransferDstOptimal,
-                    1, &copy_region);
-  src_img_->MoveLayout(cmds[0], vk::ImageLayout::eTransferDstOptimal,
+  cmd.copyImage(temp_img->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
+                src_img_->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
+                &copy_region);
+  src_img_->MoveLayout(cmd, vk::ImageLayout::eTransferDstOptimal,
                        vk::ImageLayout::eTransferSrcOptimal);
-  cmds[0].end();
-  vk->SubmitAndWait(cmds);
+  cmd.end();
+  vk->SubmitAndWait(cmd);
 
   // Create the command buffers to test the speed of copying.
-  cmds_ = vk->GetDevice().allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
   vk::ImageCopy img_copy_region;
   img_copy_region.srcSubresource.setAspectMask(vk::ImageAspectFlagBits::eColor)
       .setLayerCount(1);
@@ -90,23 +86,17 @@
   img_copy_region.extent.setWidth(img_size_.width)
       .setHeight(img_size_.height)
       .setDepth(1);
-
-  cmds_[0].begin(vk::CommandBufferBeginInfo());
-  cmds_[0].copyImage(src_img_->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
-                     dest_img_->GetImage(),
-                     vk::ImageLayout::eTransferDstOptimal, 1, &img_copy_region);
-  cmds_[0].end();
-}
-
-void CopyImage::Run() {
-  vk->SubmitAndWait(cmds_);
+  cmd.begin(vk::CommandBufferBeginInfo());
+  cmd.copyImage(src_img_->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
+                dest_img_->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
+                &img_copy_region);
+  cmd.end();
 }
 
 void CopyImage::Destroy() {
-  vk::Device device = vk->GetDevice();
+  vkbench::commandTestBase::Destroy();
   delete src_img_;
   delete dest_img_;
-  device.freeCommandBuffers(vk->GetCommandPool(), cmds_);
 }
 
 Image CopyImage::GetImage() const {
diff --git a/src/tests/copy.h b/src/tests/copy.h
index 48cfe1a..5164eff 100644
--- a/src/tests/copy.h
+++ b/src/tests/copy.h
@@ -15,26 +15,20 @@
 namespace copy {
 
 // Copy image copies the sampled image
-class CopyImage : public testBase {
+class CopyImage : public commandTestBase {
  public:
   CopyImage(uint64_t size, std::string color, vkBase* base);
   ~CopyImage() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
   Image GetImage() const override;
 
  protected:
   void Initialize() override;
-  void Run() override;
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   std::string color_;
-  std::vector<vk::CommandBuffer> cmds_;
   vk::Extent2D img_size_;
   vk::Format img_format_ = vk::Format::eR8G8B8A8Unorm;
 
diff --git a/src/tests/draw.cc b/src/tests/draw.cc
index f7bd771..7f24101 100644
--- a/src/tests/draw.cc
+++ b/src/tests/draw.cc
@@ -23,30 +23,25 @@
   CreateGraphicsPipeline();
   CreateFrameBuffers();
   // Create a cmdBuffer with draw call.
-  cmds_ = vk->GetDevice().allocateCommandBuffers(
-      {vk->GetCommandPool(), vk::CommandBufferLevel::ePrimary, 1});
-  for (const auto& buffer : cmds_) {
-    buffer.begin(vk::CommandBufferBeginInfo());
-    vk::ClearValue clear_color(std::array<float, 4>{0.f, 0.f, 0.f, 1.f});
-    vk::RenderPassBeginInfo render_pass_info;
-    render_pass_info.setFramebuffer(frame_buffer_)
-        .setRenderPass(render_pass_)
-        .setClearValueCount(1)
-        .setPClearValues(&clear_color)
-        .setRenderArea(vk::Rect2D({}, img_size_));
-    buffer.beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
-    buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, graphics_pipeline_);
-    buffer.draw(3, 1, 0, 0);
-    buffer.endRenderPass();
-    buffer.end();
-  }
-}
-
-void DrawSize::Run() {
-  vk->SubmitAndWait(cmds_);
+  vk::CommandBuffer cmd = GetCommandBuffer();
+  cmd.begin(vk::CommandBufferBeginInfo());
+  vk::ClearValue clear_color(std::array<float, 4>{0.f, 0.f, 0.f, 1.f});
+  vk::RenderPassBeginInfo render_pass_info;
+  render_pass_info.setFramebuffer(frame_buffer_)
+      .setRenderPass(render_pass_)
+      .setClearValueCount(1)
+      .setPClearValues(&clear_color)
+      .setRenderArea(vk::Rect2D({}, img_size_));
+  cmd.beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
+  cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, graphics_pipeline_);
+  cmd.draw(3, 1, 0, 0);
+  cmd.endRenderPass();
+  cmd.end();
 }
 
 void DrawSize::Destroy() {
+  vkbench::commandTestBase::Destroy();
+
   vk::Device device = vk->GetDevice();
   device.destroyImageView(img_view_);
   delete img_;
@@ -55,7 +50,6 @@
   device.destroyRenderPass(render_pass_);
   device.destroyPipeline(graphics_pipeline_);
   device.destroyPipelineLayout(pipeline_layout_);
-  device.freeCommandBuffers(vk->GetCommandPool(), cmds_);
 }
 
 void DrawSize::CreateRenderPass() {
diff --git a/src/tests/draw.h b/src/tests/draw.h
index 9172954..5a5d566 100644
--- a/src/tests/draw.h
+++ b/src/tests/draw.h
@@ -14,19 +14,16 @@
 namespace vkbench {
 namespace draw {
 
-class DrawSize : public testBase {
+class DrawSize : public commandTestBase {
  public:
   DrawSize(uint64_t size, vkBase* base);
   ~DrawSize() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
   Image GetImage() const override;
 
  protected:
   void Initialize() override;
-  void Run() override;
   void Destroy() override;
 
  private:
@@ -34,9 +31,6 @@
   void CreateGraphicsPipeline();
   void CreateFrameBuffers();
 
-  std::string name_;
-  std::string desp_;
-  std::vector<vk::CommandBuffer> cmds_;
   vk::Extent2D img_size_;
   vk::Format img_format_ = vk::Format::eR8G8B8A8Unorm;
 
diff --git a/src/tests/submit.h b/src/tests/submit.h
index 54767fe..2546c26 100644
--- a/src/tests/submit.h
+++ b/src/tests/submit.h
@@ -19,8 +19,6 @@
   BulkSubmit(uint64_t submitCnt, vkBase* base);
   ~BulkSubmit() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
 
  protected:
@@ -29,8 +27,6 @@
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   std::vector<vk::SubmitInfo> smt_infos_;
   std::vector<vk::CommandBuffer> cmd_buffers_;
   DISALLOW_COPY_AND_ASSIGN(BulkSubmit);
@@ -42,8 +38,6 @@
   MultiSubmitWaitIdle(uint64_t submitCnt, vkBase* base);
   ~MultiSubmitWaitIdle() override = default;
 
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
 
  protected:
@@ -52,8 +46,6 @@
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   std::vector<vk::Fence> fences_;
   std::vector<vk::SubmitInfo> smt_infos_;
   std::vector<vk::CommandBuffer> cmd_buffers_;
@@ -66,8 +58,6 @@
  public:
   MultiSubmitMultiWaitForFence(uint64_t submitCnt, vkBase* base);
   ~MultiSubmitMultiWaitForFence() override = default;
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
 
  protected:
@@ -76,8 +66,6 @@
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   std::vector<vk::Fence> fences_;
   std::vector<vk::SubmitInfo> smt_infos_;
   std::vector<vk::CommandBuffer> cmd_buffers_;
@@ -90,8 +78,6 @@
  public:
   MultiSubmitBulkWaitForFence(uint64_t submitCnt, vkBase* base);
   ~MultiSubmitBulkWaitForFence() override = default;
-  const char* Name() const override { return name_.c_str(); }
-  const char* Desp() const override { return desp_.c_str(); }
   const char* Unit() const override { return "us"; }
 
  protected:
@@ -100,8 +86,6 @@
   void Destroy() override;
 
  private:
-  std::string name_;
-  std::string desp_;
   std::vector<vk::Fence> fences_;
   std::vector<vk::SubmitInfo> smt_infos_;
   std::vector<vk::CommandBuffer> cmd_buffers_;