/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #define VULKAN_HPP_NAMESPACE vkhpp #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 #define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_EXCEPTIONS #define VULKAN_HPP_ASSERT_ON_RESULT #include #include #include "Expected.h" namespace gfxstream { #define VK_EXPECT(x) \ ({ \ auto expected = (x); \ if (!expected.ok()) { \ return gfxstream::unexpected(expected.error()); \ }; \ std::move(expected.value()); \ }) #define VK_EXPECT_RESULT(x) \ do { \ vkhpp::Result result = (x); \ if (result != vkhpp::Result::eSuccess) { \ return gfxstream::unexpected(result); \ } \ } while (0); #define VK_EXPECT_RV(x) \ ({ \ auto vkhpp_rv = (x); \ if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ return gfxstream::unexpected(vkhpp_rv.result); \ }; \ std::move(vkhpp_rv.value); \ }) #define VK_EXPECT_RV_OR_STRING(x) \ ({ \ auto vkhpp_rv = (x); \ if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ return gfxstream::unexpected( \ std::string("Failed to " #x ": ") + \ vkhpp::to_string(vkhpp_rv.result)); \ }; \ std::move(vkhpp_rv.value); \ }) #define VK_TRY(x) \ do { \ vkhpp::Result result = (x); \ if (result != vkhpp::Result::eSuccess) { \ return result; \ } \ } while (0); #define VK_TRY_RV(x) \ ({ \ auto vkhpp_rv = (x); \ if (vkhpp_rv.result != vkhpp::Result::eSuccess) { \ return vkhpp_rv.result; \ }; \ std::move(vkhpp_rv.value); \ }) class Vk { public: static gfxstream::expected Load( const std::vector& instance_extensions = {}, const std::vector& instance_layers = {}, const std::vector& device_extensions = {}); Vk(const Vk&) = delete; Vk& operator=(const Vk&) = delete; Vk(Vk&&) = default; Vk& operator=(Vk&&) = default; struct BufferWithMemory { vkhpp::UniqueBuffer buffer; vkhpp::UniqueDeviceMemory bufferMemory; }; gfxstream::expected CreateBuffer( vkhpp::DeviceSize buffer_size, vkhpp::BufferUsageFlags buffer_usages, vkhpp::MemoryPropertyFlags buffer_memory_properties); gfxstream::expected CreateBufferWithData( vkhpp::DeviceSize buffer_size, vkhpp::BufferUsageFlags buffer_usages, vkhpp::MemoryPropertyFlags buffer_memory_properties, const uint8_t* buffer_data); vkhpp::Result DoCommandsImmediate( const std::function& func, const std::vector& semaphores_wait = {}, const std::vector& semaphores_signal = {}); struct ImageWithMemory { vkhpp::UniqueImage image; vkhpp::UniqueDeviceMemory imageMemory; vkhpp::UniqueImageView imageView; }; gfxstream::expected CreateImage( uint32_t width, uint32_t height, vkhpp::Format format, vkhpp::ImageUsageFlags usages, vkhpp::MemoryPropertyFlags memory_properties, vkhpp::ImageLayout returned_layout); gfxstream::expected, vkhpp::Result> DownloadImage( uint32_t width, uint32_t height, const vkhpp::UniqueImage& image, vkhpp::ImageLayout current_layout, vkhpp::ImageLayout returned_layout); struct YuvImageWithMemory { vkhpp::UniqueSamplerYcbcrConversion imageSamplerConversion; vkhpp::UniqueSampler imageSampler; vkhpp::UniqueDeviceMemory imageMemory; vkhpp::UniqueImage image; vkhpp::UniqueImageView imageView; }; gfxstream::expected CreateYuvImage( uint32_t width, uint32_t height, vkhpp::ImageUsageFlags usages, vkhpp::MemoryPropertyFlags memory_properties, vkhpp::ImageLayout returned_layout); vkhpp::Result LoadYuvImage(const vkhpp::UniqueImage& image, uint32_t width, uint32_t height, const std::vector& image_data_y, const std::vector& image_data_u, const std::vector& image_data_v, vkhpp::ImageLayout current_layout, vkhpp::ImageLayout returned_layout); struct FramebufferWithAttachments { std::optional colorAttachment; std::optional depthAttachment; vkhpp::UniqueRenderPass renderpass; vkhpp::UniqueFramebuffer framebuffer; }; gfxstream::expected CreateFramebuffer( uint32_t width, uint32_t height, vkhpp::Format colorAttachmentFormat = vkhpp::Format::eUndefined, vkhpp::Format depthAttachmentFormat = vkhpp::Format::eUndefined); vkhpp::Instance& instance() { return *mInstance; } vkhpp::Device& device() { return *mDevice; } private: Vk(vkhpp::DynamicLoader loader, vkhpp::UniqueInstance instance, std::optional 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) : mLoader(std::move(loader)), mInstance(std::move(instance)), mDebugMessenger(std::move(debug)), mPhysicalDevice(std::move(physical_device)), mDevice(std::move(device)), mQueue(std::move(queue)), mQueueFamilyIndex(queue_family_index), mCommandPool(std::move(command_pool)), mStagingBuffer(std::move(stagingBuffer)), mStagingBufferMemory(std::move(stagingBufferMemory)) {} // Note: order is important for destruction. vkhpp::DynamicLoader mLoader; vkhpp::UniqueInstance mInstance; std::optional mDebugMessenger; vkhpp::PhysicalDevice mPhysicalDevice; vkhpp::UniqueDevice mDevice; vkhpp::Queue mQueue; uint32_t mQueueFamilyIndex; vkhpp::UniqueCommandPool mCommandPool; static constexpr const VkDeviceSize kStagingBufferSize = 32 * 1024 * 1024; vkhpp::UniqueBuffer mStagingBuffer; vkhpp::UniqueDeviceMemory mStagingBufferMemory; }; } // namespace cuttlefish