[impeller] [vk] Implement device buffer support (flutter/engine#34961)

This commit is contained in:
Kaushik Iska 2022-07-29 07:42:26 -04:00 committed by GitHub
parent 7d525ffed2
commit e8019563a3
6 changed files with 173 additions and 8 deletions

View File

@ -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 <memory>
_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<Texture> AllocatorVK::CreateTexture(
// |Allocator|
std::shared_ptr<DeviceBuffer> 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::NativeType>(
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<DeviceBufferAllocationVK>(
allocator_, buffer, buffer_allocation, buffer_allocation_info);
return std::make_shared<DeviceBufferVK>(length, mode, context_,
std::move(device_allocation));
}
} // namespace impeller

View File

@ -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 <memory>
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,

View File

@ -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<AllocatorVK>(new AllocatorVK(
*this, //
application_info.apiVersion, //
physical_device.value(), //
device.value.get(), //

View File

@ -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<ContextVK, Context> {
// |Context|
bool IsValid() const override;
template <typename T>
bool SetDebugName(T handle, std::string_view label) const {
uint64_t handle_ptr =
reinterpret_cast<uint64_t>(static_cast<typename T::NativeType>(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<fml::ConcurrentTaskRunner> worker_task_runner_;
vk::UniqueInstance instance_;
vk::UniqueDebugUtilsMessengerEXT debug_messenger_;
vk::UniqueDevice device_;
std::shared_ptr<AllocatorVK> allocator_;
std::shared_ptr<Allocator> allocator_;
std::shared_ptr<ShaderLibraryVK> shader_library_;
std::shared_ptr<SamplerLibraryVK> sampler_library_;
std::shared_ptr<PipelineLibraryVK> pipeline_library_;

View File

@ -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<DeviceBufferAllocationVK> 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<uint8_t*>(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

View File

@ -4,22 +4,53 @@
#pragma once
#include <memory>
#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<DeviceBufferVK, DeviceBuffer> {
public:
DeviceBufferVK(size_t size,
StorageMode mode,
ContextVK& context,
std::unique_ptr<DeviceBufferAllocationVK> device_allocation);
// |DeviceBuffer|
~DeviceBufferVK() override;
private:
friend class AllocatorVK;
DeviceBufferVK(size_t size, StorageMode mode);
ContextVK& context_;
std::unique_ptr<DeviceBufferAllocationVK> device_allocation_;
// |DeviceBuffer|
bool CopyHostBuffer(const uint8_t* source,