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