blob: 722befa27e0b9f9db293e17bba3cc0d722c1529e [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/scenic/lib/gfx/tests/vk_util.h"
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/vmo.h>
#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/impl/vulkan_utils.h"
#include <vulkan/vulkan.hpp>
namespace scenic_impl {
namespace gfx {
namespace test {
vk::DeviceMemory AllocateExportableMemory(vk::Device device, vk::PhysicalDevice physical_device,
vk::MemoryRequirements requirements,
vk::MemoryPropertyFlags flags) {
uint32_t memory_type_index =
escher::impl::GetMemoryTypeIndex(physical_device, requirements.memoryTypeBits, flags);
vk::PhysicalDeviceMemoryProperties memory_types = physical_device.getMemoryProperties();
if (memory_type_index == memory_types.memoryTypeCount) {
return nullptr;
}
vk::ExportMemoryAllocateInfoKHR export_info;
export_info.handleTypes = vk::ExternalMemoryHandleTypeFlagBits::eTempZirconVmoFUCHSIA;
vk::MemoryAllocateInfo info;
info.pNext = &export_info;
info.allocationSize = requirements.size;
info.memoryTypeIndex = memory_type_index;
vk::DeviceMemory memory = escher::ESCHER_CHECKED_VK_RESULT(device.allocateMemory(info));
return memory;
}
MemoryAllocationResult AllocateExportableMemoryDedicatedToImageIfRequired(
vk::Device device, vk::PhysicalDevice physical_device, vk::DeviceSize requested_size,
vk::Image dedicated_image, vk::MemoryPropertyFlags flags,
const vk::DispatchLoaderDynamic& dispatch) {
// We use the StructureChain provided by vulkan.hpp (see https://github.com/
// KhronosGroup/Vulkan-Hpp/blob/HEAD/README.md for details ) to get chaining
// of MemoryRequirements2 and MemoryDedicatedRequirementsKHR structures.
auto get_requirements_result =
device.getImageMemoryRequirements2KHR<vk::MemoryRequirements2KHR,
vk::MemoryDedicatedRequirementsKHR>(dedicated_image,
dispatch);
auto memory_requirements =
get_requirements_result.get<vk::MemoryRequirements2KHR>().memoryRequirements;
auto dedicated_requirements = get_requirements_result.get<vk::MemoryDedicatedRequirementsKHR>();
if (dedicated_requirements.requiresDedicatedAllocation) {
// Allocate dedicated memory, we use the allocation requirement of the image
// as the memory allocation info.
uint32_t size = memory_requirements.size;
uint32_t type = escher::impl::GetMemoryTypeIndex(physical_device,
memory_requirements.memoryTypeBits, flags);
vk::PhysicalDeviceMemoryProperties memory_types = physical_device.getMemoryProperties();
if (type == memory_types.memoryTypeCount) {
// We cannot find any memory types available for this image.
return MemoryAllocationResult{nullptr, 0u, false};
}
vk::StructureChain<vk::MemoryAllocateInfo, vk::ExportMemoryAllocateInfoKHR,
vk::MemoryDedicatedAllocateInfoKHR>
allocate_info_chain = {vk::MemoryAllocateInfo(size, type),
vk::ExportMemoryAllocateInfoKHR(
vk::ExternalMemoryHandleTypeFlagBits::eTempZirconVmoFUCHSIA),
vk::MemoryDedicatedAllocateInfoKHR(dedicated_image, vk::Buffer())};
auto result = device.allocateMemory(allocate_info_chain.get<vk::MemoryAllocateInfo>());
FX_DCHECK(result.result == vk::Result::eSuccess);
return MemoryAllocationResult{result.value, size, true};
} else {
// Allocate non-dedicated memory.
// We use the passed size argument in the memory allocation info. For memory
// type, we use 0xFFFFFFFF to represent *any* possible memory type supported
// by device as long as they support the given |flags|.
vk::MemoryRequirements requirements;
requirements.size = requested_size;
requirements.alignment = vk::DeviceSize{};
requirements.memoryTypeBits = 0xFFFFFFFF;
vk::DeviceMemory result =
AllocateExportableMemory(device, physical_device, requirements, flags);
return MemoryAllocationResult{result, requested_size, false};
}
}
zx::vmo ExportMemoryAsVmo(vk::Device device, vk::DispatchLoaderDynamic dispatch_loader,
vk::DeviceMemory memory) {
vk::MemoryGetZirconHandleInfoFUCHSIA export_memory_info(
memory, vk::ExternalMemoryHandleTypeFlagBits::eTempZirconVmoFUCHSIA);
auto result = device.getMemoryZirconHandleFUCHSIA(export_memory_info, dispatch_loader);
if (result.result != vk::Result::eSuccess) {
FX_LOGS(ERROR) << "Failed to export vk::DeviceMemory as zx::vmo";
return zx::vmo();
}
return zx::vmo(result.value);
}
vk::MemoryRequirements GetBufferRequirements(vk::Device device, vk::DeviceSize size,
vk::BufferUsageFlags usage_flags) {
// Create a temp buffer to find out memory requirements.
vk::BufferCreateInfo buffer_create_info;
buffer_create_info.size = size;
buffer_create_info.usage = usage_flags;
buffer_create_info.sharingMode = vk::SharingMode::eExclusive;
auto vk_buffer = escher::ESCHER_CHECKED_VK_RESULT(device.createBuffer(buffer_create_info));
auto retval = device.getBufferMemoryRequirements(vk_buffer);
device.destroyBuffer(vk_buffer);
return retval;
}
} // namespace test
} // namespace gfx
} // namespace scenic_impl