From e8019563a3702575ca36c85530b84ac35d07cd71 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Fri, 29 Jul 2022 07:42:26 -0400 Subject: [PATCH] [impeller] [vk] Implement device buffer support (flutter/engine#34961) --- .../renderer/backend/vulkan/allocator_vk.cc | 43 ++++++++++- .../renderer/backend/vulkan/allocator_vk.h | 7 +- .../renderer/backend/vulkan/context_vk.cc | 2 + .../renderer/backend/vulkan/context_vk.h | 24 ++++++- .../backend/vulkan/device_buffer_vk.cc | 72 ++++++++++++++++++- .../backend/vulkan/device_buffer_vk.h | 33 ++++++++- 6 files changed, 173 insertions(+), 8 deletions(-) diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc index cfb34ac69a8..c572363e6d1 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -9,17 +9,22 @@ _Pragma("GCC diagnostic ignored \"-Wthread-safety-analysis\""); #define VMA_IMPLEMENTATION #include "impeller/renderer/backend/vulkan/allocator_vk.h" +#include "impeller/renderer/backend/vulkan/device_buffer_vk.h" + +#include _Pragma("GCC diagnostic pop"); namespace impeller { -AllocatorVK::AllocatorVK(uint32_t vulkan_api_version, +AllocatorVK::AllocatorVK(ContextVK& context, + uint32_t vulkan_api_version, const vk::PhysicalDevice& physical_device, const vk::Device& logical_device, const vk::Instance& instance, PFN_vkGetInstanceProcAddr get_instance_proc_address, - PFN_vkGetDeviceProcAddr get_device_proc_address) { + PFN_vkGetDeviceProcAddr get_device_proc_address) + : context_(context) { VmaVulkanFunctions proc_table = {}; proc_table.vkGetInstanceProcAddr = get_instance_proc_address; proc_table.vkGetDeviceProcAddr = get_device_proc_address; @@ -62,7 +67,39 @@ std::shared_ptr AllocatorVK::CreateTexture( // |Allocator| std::shared_ptr AllocatorVK::CreateBuffer(StorageMode mode, size_t length) { - FML_UNREACHABLE(); + // TODO (kaushikiska): consider optimizing the usage flags based on + // StorageMode. + auto buffer_create_info = static_cast( + vk::BufferCreateInfo() + .setUsage(vk::BufferUsageFlagBits::eStorageBuffer | + vk::BufferUsageFlagBits::eTransferSrc | + vk::BufferUsageFlagBits::eTransferDst) + .setSize(length) + .setSharingMode(vk::SharingMode::eExclusive)); + + VmaAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + allocCreateInfo.flags = + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VkBuffer buffer; + VmaAllocation buffer_allocation; + VmaAllocationInfo buffer_allocation_info; + auto result = vk::Result{ + vmaCreateBuffer(allocator_, &buffer_create_info, &allocCreateInfo, + &buffer, &buffer_allocation, &buffer_allocation_info)}; + + if (result != vk::Result::eSuccess) { + VALIDATION_LOG << "Unable to allocate a device buffer"; + return nullptr; + } + + auto device_allocation = std::make_unique( + allocator_, buffer, buffer_allocation, buffer_allocation_info); + + return std::make_shared(length, mode, context_, + std::move(device_allocation)); } } // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.h index 74f20b00ab2..58141f20938 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.h @@ -6,8 +6,11 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/allocator.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" +#include + namespace impeller { class AllocatorVK final : public Allocator { @@ -19,9 +22,11 @@ class AllocatorVK final : public Allocator { friend class ContextVK; VmaAllocator allocator_ = {}; + ContextVK& context_; bool is_valid_ = false; - AllocatorVK(uint32_t vulkan_api_version, + AllocatorVK(ContextVK& context, + uint32_t vulkan_api_version, const vk::PhysicalDevice& physical_device, const vk::Device& logical_device, const vk::Instance& instance, diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc index b51234e067d..08006255503 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc @@ -12,6 +12,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/trace_event.h" #include "impeller/base/validation.h" +#include "impeller/renderer/backend/vulkan/allocator_vk.h" #include "impeller/renderer/backend/vulkan/capabilities_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -336,6 +337,7 @@ ContextVK::ContextVK( } auto allocator = std::shared_ptr(new AllocatorVK( + *this, // application_info.apiVersion, // physical_device.value(), // device.value.get(), // diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h index 5bcf5a30cc9..92e8db97335 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h @@ -10,7 +10,6 @@ #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "impeller/base/backend_cast.h" -#include "impeller/renderer/backend/vulkan/allocator_vk.h" #include "impeller/renderer/backend/vulkan/pipeline_library_vk.h" #include "impeller/renderer/backend/vulkan/sampler_library_vk.h" #include "impeller/renderer/backend/vulkan/shader_library_vk.h" @@ -34,12 +33,33 @@ class ContextVK final : public Context, public BackendCast { // |Context| bool IsValid() const override; + template + bool SetDebugName(T handle, std::string_view label) const { + uint64_t handle_ptr = + reinterpret_cast(static_cast(handle)); + + std::string label_str = std::string(label); + + auto ret = device_->setDebugUtilsObjectNameEXT( + vk::DebugUtilsObjectNameInfoEXT() + .setObjectType(T::objectType) + .setObjectHandle(handle_ptr) + .setPObjectName(label_str.c_str())); + + if (ret != vk::Result::eSuccess) { + VALIDATION_LOG << "unable to set debug name"; + return false; + } + + return true; + } + private: std::shared_ptr worker_task_runner_; vk::UniqueInstance instance_; vk::UniqueDebugUtilsMessengerEXT debug_messenger_; vk::UniqueDevice device_; - std::shared_ptr allocator_; + std::shared_ptr allocator_; std::shared_ptr shader_library_; std::shared_ptr sampler_library_; std::shared_ptr pipeline_library_; diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc index d754d43ee6c..0decd7d080c 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -4,8 +4,78 @@ #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" +#include "fml/logging.h" + namespace impeller { -// +DeviceBufferAllocationVK::DeviceBufferAllocationVK( + const VmaAllocator& allocator, + VkBuffer buffer, + VmaAllocation allocation, + VmaAllocationInfo allocation_info) + : allocator_(allocator), + buffer_(buffer), + allocation_(allocation), + allocation_info_(allocation_info) {} + +DeviceBufferAllocationVK::~DeviceBufferAllocationVK() { + if (buffer_) { + vmaDestroyBuffer(allocator_, buffer_, allocation_); + } +} + +vk::Buffer DeviceBufferAllocationVK::GetBufferHandle() const { + return buffer_; +} + +void* DeviceBufferAllocationVK::GetMapping() const { + return allocation_info_.pMappedData; +} + +DeviceBufferVK::DeviceBufferVK( + size_t size, + StorageMode mode, + ContextVK& context, + std::unique_ptr device_allocation) + : DeviceBuffer(size, mode), + context_(context), + device_allocation_(std::move(device_allocation)) {} + +DeviceBufferVK::~DeviceBufferVK() = default; + +bool DeviceBufferVK::CopyHostBuffer(const uint8_t* source, + Range source_range, + size_t offset) { + if (mode_ != StorageMode::kHostVisible) { + // One of the storage modes where a transfer queue must be used. + return false; + } + + if (offset + source_range.length > size_) { + // Out of bounds of this buffer. + return false; + } + + auto dest = static_cast(device_allocation_->GetMapping()); + + if (!dest) { + return false; + } + + if (source) { + ::memmove(dest + offset, source + source_range.offset, source_range.length); + } + + return true; +} + +bool DeviceBufferVK::SetLabel(const std::string& label) { + context_.SetDebugName(device_allocation_->GetBufferHandle(), label); + return true; +} + +bool DeviceBufferVK::SetLabel(const std::string& label, Range range) { + return SetLabel(label); +} } // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h index 19da787755c..3ea4199d74b 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h @@ -4,22 +4,53 @@ #pragma once +#include + #include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/device_buffer.h" namespace impeller { +class DeviceBufferAllocationVK { + public: + DeviceBufferAllocationVK(const VmaAllocator& allocator, + VkBuffer buffer, + VmaAllocation allocation, + VmaAllocationInfo allocation_info); + + ~DeviceBufferAllocationVK(); + + vk::Buffer GetBufferHandle() const; + + void* GetMapping() const; + + private: + const VmaAllocator& allocator_; + vk::Buffer buffer_; + VmaAllocation allocation_; + VmaAllocationInfo allocation_info_; + + FML_DISALLOW_COPY_AND_ASSIGN(DeviceBufferAllocationVK); +}; + class DeviceBufferVK final : public DeviceBuffer, public BackendCast { public: + DeviceBufferVK(size_t size, + StorageMode mode, + ContextVK& context, + std::unique_ptr device_allocation); + // |DeviceBuffer| ~DeviceBufferVK() override; private: friend class AllocatorVK; - DeviceBufferVK(size_t size, StorageMode mode); + ContextVK& context_; + std::unique_ptr device_allocation_; // |DeviceBuffer| bool CopyHostBuffer(const uint8_t* source,