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_NAMESPACE vkhpp 25 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 26 #define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 27 #define VULKAN_HPP_NO_CONSTRUCTORS 28 #define VULKAN_HPP_NO_EXCEPTIONS 29 #define VULKAN_HPP_ASSERT_ON_RESULT 30 #include <vulkan/vulkan_raii.hpp> 31 #include <vulkan/vulkan_to_string.hpp> 32 33 #include "Expected.h" 34 35 namespace gfxstream { 36 37 #define VK_EXPECT(x) \ 38 ({ \ 39 auto expected = (x); \ 40 if (!expected.ok()) { \ 41 return gfxstream::unexpected(expected.error()); \ 42 }; \ 43 std::move(expected.value()); \ 44 }) 45 46 #define VK_EXPECT_RESULT(x) \ 47 do { \ 48 vkhpp::Result result = (x); \ 49 if (result != vkhpp::Result::eSuccess) { \ 50 return gfxstream::unexpected(result); \ 51 } \ 52 } while (0); 53 54 #define VK_EXPECT_RV(x) \ 55 ({ \ 56 auto vkhpp_rv = (x); \ 57 if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ 58 return gfxstream::unexpected(vkhpp_rv.result); \ 59 }; \ 60 std::move(vkhpp_rv.value); \ 61 }) 62 63 #define VK_EXPECT_RV_OR_STRING(x) \ 64 ({ \ 65 auto vkhpp_rv = (x); \ 66 if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ 67 return gfxstream::unexpected( \ 68 std::string("Failed to " #x ": ") + \ 69 vkhpp::to_string(vkhpp_rv.result)); \ 70 }; \ 71 std::move(vkhpp_rv.value); \ 72 }) 73 74 #define VK_TRY(x) \ 75 do { \ 76 vkhpp::Result result = (x); \ 77 if (result != vkhpp::Result::eSuccess) { \ 78 return result; \ 79 } \ 80 } while (0); 81 82 #define VK_TRY_RV(x) \ 83 ({ \ 84 auto vkhpp_rv = (x); \ 85 if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ 86 return vkhpp_rv.result; \ 87 }; \ 88 std::move(vkhpp_rv.value); \ 89 }) 90 91 class Vk { 92 public: 93 static gfxstream::expected<Vk, vkhpp::Result> 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 struct BufferWithMemory { 105 vkhpp::UniqueBuffer buffer; 106 vkhpp::UniqueDeviceMemory bufferMemory; 107 }; 108 gfxstream::expected<BufferWithMemory, vkhpp::Result> CreateBuffer( 109 vkhpp::DeviceSize buffer_size, 110 vkhpp::BufferUsageFlags buffer_usages, 111 vkhpp::MemoryPropertyFlags buffer_memory_properties); 112 gfxstream::expected<BufferWithMemory, vkhpp::Result> CreateBufferWithData( 113 vkhpp::DeviceSize buffer_size, 114 vkhpp::BufferUsageFlags buffer_usages, 115 vkhpp::MemoryPropertyFlags buffer_memory_properties, 116 const uint8_t* buffer_data); 117 118 vkhpp::Result DoCommandsImmediate( 119 const std::function<vkhpp::Result(vkhpp::UniqueCommandBuffer&)>& func, 120 const std::vector<vkhpp::UniqueSemaphore>& semaphores_wait = {}, 121 const std::vector<vkhpp::UniqueSemaphore>& semaphores_signal = {}); 122 123 struct ImageWithMemory { 124 vkhpp::UniqueImage image; 125 vkhpp::UniqueDeviceMemory imageMemory; 126 vkhpp::UniqueImageView imageView; 127 }; 128 gfxstream::expected<ImageWithMemory, vkhpp::Result> CreateImage( 129 uint32_t width, 130 uint32_t height, 131 vkhpp::Format format, 132 vkhpp::ImageUsageFlags usages, 133 vkhpp::MemoryPropertyFlags memory_properties, 134 vkhpp::ImageLayout returned_layout); 135 136 gfxstream::expected<std::vector<uint8_t>, vkhpp::Result> DownloadImage( 137 uint32_t width, 138 uint32_t height, 139 const vkhpp::UniqueImage& image, 140 vkhpp::ImageLayout current_layout, 141 vkhpp::ImageLayout returned_layout); 142 143 struct YuvImageWithMemory { 144 vkhpp::UniqueSamplerYcbcrConversion imageSamplerConversion; 145 vkhpp::UniqueSampler imageSampler; 146 vkhpp::UniqueDeviceMemory imageMemory; 147 vkhpp::UniqueImage image; 148 vkhpp::UniqueImageView imageView; 149 }; 150 gfxstream::expected<YuvImageWithMemory, vkhpp::Result> CreateYuvImage( 151 uint32_t width, 152 uint32_t height, 153 vkhpp::ImageUsageFlags usages, 154 vkhpp::MemoryPropertyFlags memory_properties, 155 vkhpp::ImageLayout returned_layout); 156 157 vkhpp::Result LoadYuvImage(const vkhpp::UniqueImage& image, 158 uint32_t width, 159 uint32_t height, 160 const std::vector<uint8_t>& image_data_y, 161 const std::vector<uint8_t>& image_data_u, 162 const std::vector<uint8_t>& image_data_v, 163 vkhpp::ImageLayout current_layout, 164 vkhpp::ImageLayout returned_layout); 165 166 struct FramebufferWithAttachments { 167 std::optional<ImageWithMemory> colorAttachment; 168 std::optional<ImageWithMemory> depthAttachment; 169 vkhpp::UniqueRenderPass renderpass; 170 vkhpp::UniqueFramebuffer framebuffer; 171 }; 172 gfxstream::expected<FramebufferWithAttachments, vkhpp::Result> CreateFramebuffer( 173 uint32_t width, 174 uint32_t height, 175 vkhpp::Format colorAttachmentFormat = vkhpp::Format::eUndefined, 176 vkhpp::Format depthAttachmentFormat = vkhpp::Format::eUndefined); 177 instance()178 vkhpp::Instance& instance() { return *mInstance; } 179 device()180 vkhpp::Device& device() { return *mDevice; } 181 182 private: Vk(vkhpp::DynamicLoader loader,vkhpp::UniqueInstance instance,std::optional<vkhpp::UniqueDebugUtilsMessengerEXT> debug,vkhpp::PhysicalDevice physical_device,vkhpp::UniqueDevice device,vkhpp::Queue queue,uint32_t queue_family_index,vkhpp::UniqueCommandPool command_pool,vkhpp::UniqueBuffer stagingBuffer,vkhpp::UniqueDeviceMemory stagingBufferMemory)183 Vk(vkhpp::DynamicLoader loader, 184 vkhpp::UniqueInstance instance, 185 std::optional<vkhpp::UniqueDebugUtilsMessengerEXT> debug, 186 vkhpp::PhysicalDevice physical_device, 187 vkhpp::UniqueDevice device, 188 vkhpp::Queue queue, 189 uint32_t queue_family_index, 190 vkhpp::UniqueCommandPool command_pool, 191 vkhpp::UniqueBuffer stagingBuffer, 192 vkhpp::UniqueDeviceMemory stagingBufferMemory) 193 : mLoader(std::move(loader)), 194 mInstance(std::move(instance)), 195 mDebugMessenger(std::move(debug)), 196 mPhysicalDevice(std::move(physical_device)), 197 mDevice(std::move(device)), 198 mQueue(std::move(queue)), 199 mQueueFamilyIndex(queue_family_index), 200 mCommandPool(std::move(command_pool)), 201 mStagingBuffer(std::move(stagingBuffer)), 202 mStagingBufferMemory(std::move(stagingBufferMemory)) {} 203 204 // Note: order is important for destruction. 205 vkhpp::DynamicLoader mLoader; 206 vkhpp::UniqueInstance mInstance; 207 std::optional<vkhpp::UniqueDebugUtilsMessengerEXT> mDebugMessenger; 208 vkhpp::PhysicalDevice mPhysicalDevice; 209 vkhpp::UniqueDevice mDevice; 210 vkhpp::Queue mQueue; 211 uint32_t mQueueFamilyIndex; 212 vkhpp::UniqueCommandPool mCommandPool; 213 static constexpr const VkDeviceSize kStagingBufferSize = 32 * 1024 * 1024; 214 vkhpp::UniqueBuffer mStagingBuffer; 215 vkhpp::UniqueDeviceMemory mStagingBufferMemory; 216 }; 217 218 } // namespace cuttlefish 219