• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <functional>
20 #include <optional>
21 #include <string>
22 #include <vector>
23 
24 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
25 #define VULKAN_HPP_NO_CONSTRUCTORS
26 #define VULKAN_HPP_NO_EXCEPTIONS
27 #include <vulkan/vulkan_raii.hpp>
28 #include <vulkan/vulkan_to_string.hpp>
29 
30 namespace cuttlefish {
31 
32 // For a function:
33 //
34 //   android::base::expected<vk::Type, vk::Result> Foo();
35 //
36 // simplifies
37 //
38 //   auto obj_expect = Foo();
39 //   if (!obj_expect.ok()) {
40 //     return expect.error();
41 //   }
42 //   auto obj = std::move(obj.value());
43 //
44 // to
45 //
46 //   auto obj = VK_EXPECT(Foo());
47 #define VK_EXPECT(x)                                    \
48   ({                                                    \
49     auto vk_expect_android_base_expected = (x);         \
50     if (!vk_expect_android_base_expected.ok()) {        \
51       return android::base::unexpected(                 \
52           vk_expect_android_base_expected.error());     \
53     };                                                  \
54     std::move(vk_expect_android_base_expected.value()); \
55   })
56 
57 #define VK_EXPECT_RESULT(x)                             \
58   ({                                                    \
59     auto vk_expect_android_base_expected = (x);         \
60     if (!vk_expect_android_base_expected.ok()) {        \
61       return vk_expect_android_base_expected.error();   \
62     };                                                  \
63     std::move(vk_expect_android_base_expected.value()); \
64   })
65 
66 #define VK_RETURN_IF_NOT_SUCCESS(x)                    \
67   do {                                                 \
68     vk::Result result = (x);                           \
69     if (result != vk::Result::eSuccess) return result; \
70   } while (0);
71 
72 #define VK_RETURN_UNEXPECTED_IF_NOT_SUCCESS(x)  \
73   do {                                          \
74     vk::Result result = (x);                    \
75     if (result != vk::Result::eSuccess) {       \
76       return android::base::unexpected(result); \
77     }                                           \
78   } while (0);
79 
80 #define VK_ASSERT(x)                                                          \
81   do {                                                                        \
82     if (vk::Result result = (x); result != vk::Result::eSuccess) {            \
83       LOG(FATAL) << __FILE__ << ":" << __LINE__ << ":" << __PRETTY_FUNCTION__ \
84                  << ": " << #x << " returned " << to_string(result);          \
85     }                                                                         \
86   } while (0);
87 
88 template <typename VkType>
89 using VkExpected = android::base::expected<VkType, vk::Result>;
90 
91 class Vk {
92  public:
93   static std::optional<Vk> Load(
94       const std::vector<std::string>& instance_extensions = {},
95       const std::vector<std::string>& instance_layers = {},
96       const std::vector<std::string>& device_extensions = {});
97 
98   Vk(const Vk&) = delete;
99   Vk& operator=(const Vk&) = delete;
100 
101   Vk(Vk&&) = default;
102   Vk& operator=(Vk&&) = default;
103 
104   // Note: order is important for destruction.
105  private:
106   static VkExpected<Vk> LoadImpl(
107       const std::vector<std::string>& instance_extensions = {},
108       const std::vector<std::string>& instance_layers = {},
109       const std::vector<std::string>& device_extensions = {});
110 
111   vk::DynamicLoader vk_loader_;
112   vk::raii::Context vk_context_;
113 
114  public:
115   vk::raii::Instance vk_instance;
116 
117  private:
118   std::optional<vk::raii::DebugUtilsMessengerEXT> vk_debug_messenger_;
119 
120  public:
121   vk::raii::PhysicalDevice vk_physical_device;
122   vk::raii::Device vk_device;
123   vk::raii::Queue vk_queue;
124   uint32_t vk_queue_family_index;
125 
126  private:
127   vk::raii::CommandPool vk_command_pool_;
128   static constexpr const VkDeviceSize kStagingBufferSize = 32 * 1024 * 1024;
129   vk::raii::Buffer vk_staging_buffer_;
130   vk::raii::DeviceMemory vk_staging_buffer_memory_;
131 
132  public:
133   struct BufferWithMemory {
134     vk::raii::Buffer buffer;
135     vk::raii::DeviceMemory buffer_memory;
136   };
137 
138   VkExpected<BufferWithMemory> CreateBuffer(
139       vk::DeviceSize buffer_size, vk::BufferUsageFlags buffer_usages,
140       vk::MemoryPropertyFlags buffer_memory_properties);
141 
142   VkExpected<BufferWithMemory> CreateBufferWithData(
143       vk::DeviceSize buffer_size, vk::BufferUsageFlags buffer_usages,
144       vk::MemoryPropertyFlags buffer_memory_properties,
145       const uint8_t* buffer_data);
146 
147   vk::Result DoCommandsImmediate(
148       const std::function<vk::Result(vk::raii::CommandBuffer&)>& func,
149       const std::vector<vk::raii::Semaphore>& semaphores_wait = {},
150       const std::vector<vk::raii::Semaphore>& semaphores_signal = {});
151 
152   struct ImageWithMemory {
153     vk::raii::DeviceMemory image_memory;
154     vk::raii::Image image;
155     vk::raii::ImageView image_view;
156   };
157   VkExpected<ImageWithMemory> CreateImage(
158       uint32_t width, uint32_t height, vk::Format format,
159       vk::ImageUsageFlags usages, vk::MemoryPropertyFlags memory_properties,
160       vk::ImageLayout returned_layout);
161 
162   vk::Result DownloadImage(uint32_t width, uint32_t height,
163                            const vk::raii::Image& image,
164                            vk::ImageLayout current_layout,
165                            vk::ImageLayout returned_layout,
166                            std::vector<uint8_t>* out_pixels);
167 
168   struct YuvImageWithMemory {
169     vk::raii::SamplerYcbcrConversion image_sampler_conversion;
170     vk::raii::Sampler image_sampler;
171     vk::raii::DeviceMemory image_memory;
172     vk::raii::Image image;
173     vk::raii::ImageView image_view;
174   };
175 
176   VkExpected<YuvImageWithMemory> CreateYuvImage(
177       uint32_t width, uint32_t height, vk::ImageUsageFlags usages,
178       vk::MemoryPropertyFlags memory_properties,
179       vk::ImageLayout returned_layout);
180 
181   vk::Result LoadYuvImage(const vk::raii::Image& image, uint32_t width,
182                           uint32_t height,
183                           const std::vector<uint8_t>& image_data_y,
184                           const std::vector<uint8_t>& image_data_u,
185                           const std::vector<uint8_t>& image_data_v,
186                           vk::ImageLayout current_layout,
187                           vk::ImageLayout returned_layout);
188 
189   struct FramebufferWithAttachments {
190     std::optional<ImageWithMemory> color_attachment;
191     std::optional<ImageWithMemory> depth_attachment;
192     vk::raii::RenderPass renderpass;
193     vk::raii::Framebuffer framebuffer;
194   };
195   VkExpected<FramebufferWithAttachments> CreateFramebuffer(
196       uint32_t width, uint32_t height,
197       vk::Format color_attachment_format = vk::Format::eUndefined,
198       vk::Format depth_attachment_format = vk::Format::eUndefined);
199 
200  private:
Vk(vk::DynamicLoader loader,vk::raii::Context context,vk::raii::Instance instance,std::optional<vk::raii::DebugUtilsMessengerEXT> debug,vk::raii::PhysicalDevice physical_device,vk::raii::Device device,vk::raii::Queue queue,uint32_t queue_family_index,vk::raii::CommandPool command_pool,vk::raii::Buffer staging_buffer,vk::raii::DeviceMemory staging_buffer_memory)201   Vk(vk::DynamicLoader loader, vk::raii::Context context,
202      vk::raii::Instance instance,
203      std::optional<vk::raii::DebugUtilsMessengerEXT> debug,
204      vk::raii::PhysicalDevice physical_device, vk::raii::Device device,
205      vk::raii::Queue queue, uint32_t queue_family_index,
206      vk::raii::CommandPool command_pool, vk::raii::Buffer staging_buffer,
207      vk::raii::DeviceMemory staging_buffer_memory)
208       : vk_loader_(std::move(loader)),
209         vk_context_(std::move(context)),
210         vk_instance(std::move(instance)),
211         vk_debug_messenger_(std::move(debug)),
212         vk_physical_device(std::move(physical_device)),
213         vk_device(std::move(device)),
214         vk_queue(std::move(queue)),
215         vk_queue_family_index(queue_family_index),
216         vk_command_pool_(std::move(command_pool)),
217         vk_staging_buffer_(std::move(staging_buffer)),
218         vk_staging_buffer_memory_(std::move(staging_buffer_memory)) {}
219 };
220 
221 }  // namespace cuttlefish
222