157 lines
7.0 KiB
C++
157 lines
7.0 KiB
C++
// Copyright 2019 The Dawn Authors
|
|
//
|
|
// 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.
|
|
|
|
#include "common/Assert.h"
|
|
#include "dawn_native/vulkan/AdapterVk.h"
|
|
#include "dawn_native/vulkan/BackendVk.h"
|
|
#include "dawn_native/vulkan/DeviceVk.h"
|
|
#include "dawn_native/vulkan/TextureVk.h"
|
|
#include "dawn_native/vulkan/VulkanError.h"
|
|
#include "dawn_native/vulkan/external_memory/MemoryService.h"
|
|
|
|
namespace dawn_native { namespace vulkan { namespace external_memory {
|
|
|
|
Service::Service(Device* device)
|
|
: mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {
|
|
}
|
|
|
|
Service::~Service() = default;
|
|
|
|
// static
|
|
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) {
|
|
return deviceInfo.HasExt(DeviceExt::ExternalMemoryZirconHandle);
|
|
}
|
|
|
|
bool Service::SupportsImportMemory(VkFormat format,
|
|
VkImageType type,
|
|
VkImageTiling tiling,
|
|
VkImageUsageFlags usage,
|
|
VkImageCreateFlags flags) {
|
|
// Early out before we try using extension functions
|
|
if (!mSupported) {
|
|
return false;
|
|
}
|
|
|
|
VkPhysicalDeviceExternalImageFormatInfo externalFormatInfo;
|
|
externalFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
|
|
externalFormatInfo.pNext = nullptr;
|
|
externalFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
|
|
|
VkPhysicalDeviceImageFormatInfo2 formatInfo;
|
|
formatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
|
|
formatInfo.pNext = &externalFormatInfo;
|
|
formatInfo.format = format;
|
|
formatInfo.type = type;
|
|
formatInfo.tiling = tiling;
|
|
formatInfo.usage = usage;
|
|
formatInfo.flags = flags;
|
|
|
|
VkExternalImageFormatProperties externalFormatProperties;
|
|
externalFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR;
|
|
externalFormatProperties.pNext = nullptr;
|
|
|
|
VkImageFormatProperties2 formatProperties;
|
|
formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
|
|
formatProperties.pNext = &externalFormatProperties;
|
|
|
|
VkResult result = mDevice->fn.GetPhysicalDeviceImageFormatProperties2(
|
|
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties);
|
|
|
|
// If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED
|
|
if (result != VK_SUCCESS) {
|
|
return false;
|
|
}
|
|
|
|
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
|
|
VkFlags memoryFlags =
|
|
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
|
|
return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0;
|
|
}
|
|
|
|
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
|
|
VkFormat format,
|
|
VkImageUsageFlags usage) {
|
|
return mSupported;
|
|
}
|
|
|
|
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
|
const ExternalImageDescriptor* descriptor,
|
|
VkImage image) {
|
|
DAWN_INVALID_IF(descriptor->type != ExternalImageType::OpaqueFD,
|
|
"ExternalImageDescriptor is not an OpaqueFD descriptor.");
|
|
|
|
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
|
static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor);
|
|
|
|
MemoryImportParams params = {opaqueFDDescriptor->allocationSize,
|
|
opaqueFDDescriptor->memoryTypeIndex};
|
|
return params;
|
|
}
|
|
|
|
ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
|
|
const MemoryImportParams& importParams,
|
|
VkImage image) {
|
|
DAWN_INVALID_IF(handle == ZX_HANDLE_INVALID, "Importing memory with an invalid handle.");
|
|
|
|
VkMemoryRequirements requirements;
|
|
mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements);
|
|
DAWN_INVALID_IF(
|
|
requirements.size > importParams.allocationSize,
|
|
"Requested allocation size (%u) is smaller than the required image size (%u).",
|
|
importParams.allocationSize, requirements.size);
|
|
|
|
VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo;
|
|
importMemoryHandleInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA;
|
|
importMemoryHandleInfo.pNext = nullptr;
|
|
importMemoryHandleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
|
importMemoryHandleInfo.handle = handle;
|
|
|
|
VkMemoryAllocateInfo allocateInfo;
|
|
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
allocateInfo.pNext = &importMemoryHandleInfo;
|
|
allocateInfo.allocationSize = importParams.allocationSize;
|
|
allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex;
|
|
|
|
VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
|
|
DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo,
|
|
nullptr, &*allocatedMemory),
|
|
"vkAllocateMemory"));
|
|
return allocatedMemory;
|
|
}
|
|
|
|
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
|
const VkImageCreateInfo& baseCreateInfo) {
|
|
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo;
|
|
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
|
externalMemoryImageCreateInfo.pNext = nullptr;
|
|
externalMemoryImageCreateInfo.handleTypes =
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
|
|
|
VkImageCreateInfo createInfo = baseCreateInfo;
|
|
createInfo.pNext = &externalMemoryImageCreateInfo;
|
|
createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
|
|
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
ASSERT(IsSampleCountSupported(mDevice, createInfo));
|
|
|
|
VkImage image;
|
|
DAWN_TRY(CheckVkSuccess(
|
|
mDevice->fn.CreateImage(mDevice->GetVkDevice(), &createInfo, nullptr, &*image),
|
|
"CreateImage"));
|
|
return image;
|
|
}
|
|
|
|
}}} // namespace dawn_native::vulkan::external_memory
|