blob: 1fd3ac0adc32baecb6a41cb6aae0b5f040518aa6 [file] [log] [blame]
// Copyright (c) 2018 The Chromium 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 "gpu/vulkan/android/vulkan_implementation_android.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_instance.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "ui/gfx/gpu_fence.h"
namespace gpu {
VulkanImplementationAndroid::VulkanImplementationAndroid() = default;
VulkanImplementationAndroid::~VulkanImplementationAndroid() = default;
bool VulkanImplementationAndroid::InitializeVulkanInstance() {
std::vector<const char*> required_extensions = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME};
VulkanFunctionPointers* vulkan_function_pointers =
gpu::GetVulkanFunctionPointers();
base::NativeLibraryLoadError native_library_load_error;
vulkan_function_pointers->vulkan_loader_library_ = base::LoadNativeLibrary(
base::FilePath("libvulkan.so"), &native_library_load_error);
if (!vulkan_function_pointers->vulkan_loader_library_)
return false;
if (!vulkan_instance_.Initialize(required_extensions, {})) {
vulkan_instance_.Destroy();
return false;
}
// Initialize platform function pointers
vkCreateAndroidSurfaceKHR_ =
reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(vkGetInstanceProcAddr(
vulkan_instance_.vk_instance(), "vkCreateAndroidSurfaceKHR"));
if (!vkCreateAndroidSurfaceKHR_) {
LOG(ERROR) << "vkCreateAndroidSurfaceKHR not found";
vulkan_instance_.Destroy();
return false;
}
return true;
}
VkInstance VulkanImplementationAndroid::GetVulkanInstance() {
return vulkan_instance_.vk_instance();
}
std::unique_ptr<VulkanSurface> VulkanImplementationAndroid::CreateViewSurface(
gfx::AcceleratedWidget window) {
VkSurfaceKHR surface;
VkAndroidSurfaceCreateInfoKHR surface_create_info = {};
surface_create_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
surface_create_info.window = window;
VkResult result = vkCreateAndroidSurfaceKHR_(
GetVulkanInstance(), &surface_create_info, nullptr, &surface);
if (VK_SUCCESS != result) {
DLOG(ERROR) << "vkCreateAndroidSurfaceKHR() failed: " << result;
return nullptr;
}
return std::make_unique<VulkanSurface>(GetVulkanInstance(), surface);
}
bool VulkanImplementationAndroid::GetPhysicalDevicePresentationSupport(
VkPhysicalDevice device,
const std::vector<VkQueueFamilyProperties>& queue_family_properties,
uint32_t queue_family_index) {
// On Android, all physical devices and queue families must be capable of
// presentation with any native window.
// As a result there is no Android-specific query for these capabilities.
return true;
}
std::vector<const char*>
VulkanImplementationAndroid::GetRequiredDeviceExtensions() {
return {VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME};
}
VkFence VulkanImplementationAndroid::CreateVkFenceForGpuFence(
VkDevice vk_device) {
NOTREACHED();
return VK_NULL_HANDLE;
}
std::unique_ptr<gfx::GpuFence>
VulkanImplementationAndroid::ExportVkFenceToGpuFence(VkDevice vk_device,
VkFence vk_fence) {
NOTREACHED();
return nullptr;
}
bool VulkanImplementationAndroid::ImportSemaphoreFdKHR(
VkDevice vk_device,
base::ScopedFD sync_fd,
VkSemaphore* vk_semaphore) {
// Create a VkSemaphore.
VkSemaphoreCreateInfo info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
bool result = vkCreateSemaphore(vk_device, &info, nullptr, vk_semaphore);
if (result != VK_SUCCESS) {
LOG(ERROR) << "vkCreateSemaphore failed : " << result;
return false;
}
// Create VkImportSemaphoreFdInfoKHR structure.
VkImportSemaphoreFdInfoKHR import;
import.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
import.pNext = nullptr;
import.semaphore = *vk_semaphore;
import.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR;
// VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT specifies a POSIX file
// descriptor handle to a Linux Sync File or Android Fence object.
import.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
import.fd = sync_fd.get();
// Import the fd into the semaphore.
result = vkImportSemaphoreFdKHR(vk_device, &import);
if (result != VK_SUCCESS) {
LOG(ERROR) << "vkImportSemaphoreFdKHR failed : " << result;
vkDestroySemaphore(vk_device, *vk_semaphore, nullptr);
return false;
}
// If import is successful, the VkSemaphore object takes the ownership of fd.
ignore_result(sync_fd.release());
return true;
}
bool VulkanImplementationAndroid::GetSemaphoreFdKHR(VkDevice vk_device,
VkSemaphore vk_semaphore,
base::ScopedFD* sync_fd) {
// Create VkSemaphoreGetFdInfoKHR structure.
VkSemaphoreGetFdInfoKHR info;
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
info.pNext = nullptr;
info.semaphore = vk_semaphore;
info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
// Create a new sync fd from the semaphore.
int fd = -1;
bool result = vkGetSemaphoreFdKHR(vk_device, &info, &fd);
if (result != VK_SUCCESS) {
LOG(ERROR) << "vkGetSemaphoreFdKHR failed : " << result;
sync_fd->reset(-1);
return false;
}
// Transfer the ownership of the fd to the caller.
sync_fd->reset(fd);
return true;
}
} // namespace gpu