• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/vulkan/command_buffer.h"
16 
17 #include <cassert>
18 
19 #include "src/vulkan/command_pool.h"
20 #include "src/vulkan/device.h"
21 
22 namespace amber {
23 namespace vulkan {
24 
CommandBuffer(Device * device,CommandPool * pool)25 CommandBuffer::CommandBuffer(Device* device, CommandPool* pool)
26     : device_(device), pool_(pool) {}
27 
~CommandBuffer()28 CommandBuffer::~CommandBuffer() {
29   Reset();
30 
31   if (fence_ != VK_NULL_HANDLE)
32     device_->GetPtrs()->vkDestroyFence(device_->GetVkDevice(), fence_, nullptr);
33 
34   if (command_ != VK_NULL_HANDLE) {
35     device_->GetPtrs()->vkFreeCommandBuffers(
36         device_->GetVkDevice(), pool_->GetVkCommandPool(), 1, &command_);
37   }
38 }
39 
Initialize()40 Result CommandBuffer::Initialize() {
41   VkCommandBufferAllocateInfo command_info = VkCommandBufferAllocateInfo();
42   command_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
43   command_info.commandPool = pool_->GetVkCommandPool();
44   command_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
45   command_info.commandBufferCount = 1;
46 
47   if (device_->GetPtrs()->vkAllocateCommandBuffers(
48           device_->GetVkDevice(), &command_info, &command_) != VK_SUCCESS) {
49     return Result("Vulkan::Calling vkAllocateCommandBuffers Fail");
50   }
51 
52   VkFenceCreateInfo fence_info = VkFenceCreateInfo();
53   fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
54   if (device_->GetPtrs()->vkCreateFence(device_->GetVkDevice(), &fence_info,
55                                         nullptr, &fence_) != VK_SUCCESS) {
56     return Result("Vulkan::Calling vkCreateFence Fail");
57   }
58 
59   return {};
60 }
61 
BeginRecording()62 Result CommandBuffer::BeginRecording() {
63   VkCommandBufferBeginInfo command_begin_info = VkCommandBufferBeginInfo();
64   command_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
65   command_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
66   if (device_->GetPtrs()->vkBeginCommandBuffer(command_, &command_begin_info) !=
67       VK_SUCCESS) {
68     return Result("Vulkan::Calling vkBeginCommandBuffer Fail");
69   }
70   guarded_ = true;
71 
72   return {};
73 }
74 
SubmitAndReset(uint32_t timeout_ms)75 Result CommandBuffer::SubmitAndReset(uint32_t timeout_ms) {
76   if (device_->GetPtrs()->vkEndCommandBuffer(command_) != VK_SUCCESS)
77     return Result("Vulkan::Calling vkEndCommandBuffer Fail");
78 
79   if (device_->GetPtrs()->vkResetFences(device_->GetVkDevice(), 1, &fence_) !=
80       VK_SUCCESS) {
81     return Result("Vulkan::Calling vkResetFences Fail");
82   }
83 
84   VkSubmitInfo submit_info = VkSubmitInfo();
85   submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
86   submit_info.commandBufferCount = 1;
87   submit_info.pCommandBuffers = &command_;
88   if (device_->GetPtrs()->vkQueueSubmit(device_->GetVkQueue(), 1, &submit_info,
89                                         fence_) != VK_SUCCESS) {
90     return Result("Vulkan::Calling vkQueueSubmit Fail");
91   }
92 
93   guarded_ = false;
94 
95   VkResult r = device_->GetPtrs()->vkWaitForFences(
96       device_->GetVkDevice(), 1, &fence_, VK_TRUE,
97       static_cast<uint64_t>(timeout_ms) * 1000ULL * 1000ULL /* nanosecond */);
98   if (r == VK_TIMEOUT)
99     return Result("Vulkan::Calling vkWaitForFences Timeout");
100   if (r != VK_SUCCESS)
101     return Result("Vulkan::Calling vkWaitForFences Fail");
102 
103   if (device_->GetPtrs()->vkResetCommandBuffer(command_, 0) != VK_SUCCESS)
104     return Result("Vulkan::Calling vkResetCommandBuffer Fail");
105 
106   return {};
107 }
108 
Reset()109 void CommandBuffer::Reset() {
110   if (guarded_) {
111     device_->GetPtrs()->vkEndCommandBuffer(command_);
112     device_->GetPtrs()->vkResetCommandBuffer(command_, 0);
113     guarded_ = false;
114   }
115 }
116 
CommandBufferGuard(CommandBuffer * buffer)117 CommandBufferGuard::CommandBufferGuard(CommandBuffer* buffer)
118     : buffer_(buffer) {
119   assert(!buffer_->guarded_);
120   result_ = buffer_->BeginRecording();
121 }
122 
~CommandBufferGuard()123 CommandBufferGuard::~CommandBufferGuard() {
124   if (buffer_->guarded_)
125     buffer_->Reset();
126 }
127 
Submit(uint32_t timeout_ms)128 Result CommandBufferGuard::Submit(uint32_t timeout_ms) {
129   assert(buffer_->guarded_);
130   return buffer_->SubmitAndReset(timeout_ms);
131 }
132 
133 }  // namespace vulkan
134 }  // namespace amber
135