Commit 7af47362 authored by Vikas Soni's avatar Vikas Soni Committed by Commit Bot

Export/Import sync FD from/to a Vulkan Semaphore.

Added android utility functions to export/import sync FD from/to a
vulkan semaphore. Added unittests.

Bug: 891060
Change-Id: I2fcac73018fe91afae0ac141fdd5e40244451b15
Reviewed-on: https://chromium-review.googlesource.com/c/1332608Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: vikas soni <vikassoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611399}
parent dab98eb1
......@@ -52,11 +52,15 @@ if (enable_vulkan) {
"viz_vulkan_context_provider_export.h",
]
configs = [ "//third_party/vulkan:vulkan_config" ]
public_deps = [
"//skia",
]
deps = [
"//base",
"//gpu/vulkan",
"//gpu/vulkan:buildflags",
"//skia",
]
}
}
......
......@@ -4,6 +4,7 @@
import("//build/config/ui.gni")
import("//gpu/vulkan/features.gni")
import("//testing/test.gni")
assert(enable_vulkan)
assert(is_android)
......@@ -22,7 +23,9 @@ component("android") {
defines = [ "IS_VULKAN_ANDROID_IMPL" ]
deps = [ "//ui/gfx" ]
deps = [
"//ui/gfx",
]
public_configs = [ ":vulkan_android" ]
......@@ -31,3 +34,17 @@ component("android") {
"//gpu/vulkan",
]
}
test("vk_tests") {
deps = [
":android",
"//base:base",
"//base/test:test_support",
"//components/viz/common:vulkan_context_provider",
"//testing/gtest",
]
sources = [
"run_all_unittests.cc",
"vulkan_android_unittests.cc",
]
}
include_rules = [
"+components/viz/common/gpu",
]
// Copyright 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 "base/bind.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
int main(int argc, char** argv) {
base::TestSuite test_suite(argc, argv);
return base::LaunchUnitTests(
argc, argv,
base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
}
// Copyright 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 <sys/eventfd.h>
#include "base/files/scoped_file.h"
#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "gpu/vulkan/android/vulkan_implementation_android.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gpu {
class VulkanImplementationAndroidTest : public testing::Test {
public:
void SetUp() override {
// Create a vulkan implementation.
vk_implementation_ = std::make_unique<VulkanImplementationAndroid>();
ASSERT_TRUE(vk_implementation_);
ASSERT_TRUE(vk_implementation_->InitializeVulkanInstance());
// Create vulkan context provider.
vk_context_provider_ =
viz::VulkanInProcessContextProvider::Create(vk_implementation_.get());
ASSERT_TRUE(vk_context_provider_);
// Get the VkDevice.
vk_device_ = vk_context_provider_->GetDeviceQueue()->GetVulkanDevice();
ASSERT_TRUE(vk_device_);
}
void TearDown() override {
vk_context_provider_->Destroy();
vk_device_ = VK_NULL_HANDLE;
}
protected:
std::unique_ptr<VulkanImplementationAndroid> vk_implementation_;
scoped_refptr<viz::VulkanInProcessContextProvider> vk_context_provider_;
VkDevice vk_device_;
};
TEST_F(VulkanImplementationAndroidTest, ExportImportSyncFd) {
// Create a vk semaphore which can be exported.
// To create a semaphore whose payload can be exported to external handles,
// add the VkExportSemaphoreCreateInfo structure to the pNext chain of the
// VkSemaphoreCreateInfo structure.
VkExportSemaphoreCreateInfo export_info;
export_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
export_info.pNext = nullptr;
export_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
VkSemaphore semaphore1;
VkSemaphoreCreateInfo sem_info;
sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
sem_info.pNext = &export_info;
sem_info.flags = 0;
bool result = vkCreateSemaphore(vk_device_, &sem_info, nullptr, &semaphore1);
EXPECT_EQ(result, VK_SUCCESS);
// SYNC_FD semaphores must be signalled or have an associated semaphore
// signal operation pending execution before the export.
// Semaphores can be signaled by including them in a batch as part of a queue
// submission command, defining a queue operation to signal that semaphore.
unsigned int submit_count = 1;
VkFence fence = VK_NULL_HANDLE;
VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &semaphore1;
result =
vkQueueSubmit(vk_context_provider_->GetDeviceQueue()->GetVulkanQueue(),
submit_count, &submit_info, fence);
EXPECT_EQ(result, VK_SUCCESS);
// Export a sync fd from the semaphore.
base::ScopedFD sync_fd;
EXPECT_TRUE(
vk_implementation_->GetSemaphoreFdKHR(vk_device_, semaphore1, &sync_fd));
EXPECT_GT(sync_fd.get(), -1);
// Import the above sync fd into a new semaphore.
VkSemaphore semaphore2;
EXPECT_TRUE(vk_implementation_->ImportSemaphoreFdKHR(
vk_device_, std::move(sync_fd), &semaphore2));
// Wait for the device to be idle.
result = vkDeviceWaitIdle(vk_device_);
EXPECT_EQ(result, VK_SUCCESS);
// Destroy the semaphores.
vkDestroySemaphore(vk_device_, semaphore1, nullptr);
vkDestroySemaphore(vk_device_, semaphore2, nullptr);
}
} // namespace gpu
......@@ -6,6 +6,7 @@
#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"
......@@ -19,7 +20,10 @@ 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_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();
......@@ -80,7 +84,9 @@ bool VulkanImplementationAndroid::GetPhysicalDevicePresentationSupport(
std::vector<const char*>
VulkanImplementationAndroid::GetRequiredDeviceExtensions() {
return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
return {VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME};
}
VkFence VulkanImplementationAndroid::CreateVkFenceForGpuFence(
......@@ -96,4 +102,65 @@ VulkanImplementationAndroid::ExportVkFenceToGpuFence(VkDevice vk_device,
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
......@@ -34,6 +34,12 @@ class COMPONENT_EXPORT(VULKAN_ANDROID) VulkanImplementationAndroid
std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(
VkDevice vk_device,
VkFence vk_fence) override;
bool ImportSemaphoreFdKHR(VkDevice vk_device,
base::ScopedFD sync_fd,
VkSemaphore* vk_semaphore) override;
bool GetSemaphoreFdKHR(VkDevice vk_device,
VkSemaphore vk_semaphore,
base::ScopedFD* sync_fd) override;
private:
VulkanInstance vulkan_instance_;
......
......@@ -61,6 +61,7 @@ VULKAN_DEVICE_FUNCTIONS = [
{ 'name': 'vkDestroySampler' },
{ 'name': 'vkDestroySemaphore' },
{ 'name': 'vkDestroyShaderModule' },
{ 'name': 'vkDeviceWaitIdle' },
{ 'name': 'vkFreeCommandBuffers' },
{ 'name': 'vkFreeDescriptorSets' },
{ 'name': 'vkFreeMemory' },
......
......@@ -223,6 +223,11 @@ bool VulkanFunctionPointers::BindDeviceFunctionPointers(VkDevice vk_device) {
if (!vkDestroyShaderModuleFn)
return false;
vkDeviceWaitIdleFn = reinterpret_cast<PFN_vkDeviceWaitIdle>(
vkGetDeviceProcAddrFn(vk_device, "vkDeviceWaitIdle"));
if (!vkDeviceWaitIdleFn)
return false;
vkFreeCommandBuffersFn = reinterpret_cast<PFN_vkFreeCommandBuffers>(
vkGetDeviceProcAddrFn(vk_device, "vkFreeCommandBuffers"));
if (!vkFreeCommandBuffersFn)
......
......@@ -91,6 +91,7 @@ struct VulkanFunctionPointers {
PFN_vkDestroySampler vkDestroySamplerFn = nullptr;
PFN_vkDestroySemaphore vkDestroySemaphoreFn = nullptr;
PFN_vkDestroyShaderModule vkDestroyShaderModuleFn = nullptr;
PFN_vkDeviceWaitIdle vkDeviceWaitIdleFn = nullptr;
PFN_vkFreeCommandBuffers vkFreeCommandBuffersFn = nullptr;
PFN_vkFreeDescriptorSets vkFreeDescriptorSetsFn = nullptr;
PFN_vkFreeMemory vkFreeMemoryFn = nullptr;
......@@ -202,6 +203,7 @@ struct VulkanFunctionPointers {
gpu::GetVulkanFunctionPointers()->vkDestroySemaphoreFn
#define vkDestroyShaderModule \
gpu::GetVulkanFunctionPointers()->vkDestroyShaderModuleFn
#define vkDeviceWaitIdle gpu::GetVulkanFunctionPointers()->vkDeviceWaitIdleFn
#define vkFreeCommandBuffers \
gpu::GetVulkanFunctionPointers()->vkFreeCommandBuffersFn
#define vkFreeDescriptorSets \
......
......@@ -8,7 +8,9 @@
#include <vulkan/vulkan.h>
#include <memory>
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "gpu/vulkan/vulkan_export.h"
#include "ui/gfx/native_widget_types.h"
......@@ -53,6 +55,22 @@ class VULKAN_EXPORT VulkanImplementation {
VkDevice vk_device,
VkFence vk_fence) = 0;
#if defined(OS_ANDROID)
// Import a VkSemaphore from a POSIX sync file descriptor. Importing a
// semaphore payload from a file descriptor transfers ownership of the file
// descriptor from the application to the Vulkan implementation. The
// application must not perform any operations on the file descriptor after a
// successful import.
virtual bool ImportSemaphoreFdKHR(VkDevice vk_device,
base::ScopedFD sync_fd,
VkSemaphore* vk_semaphore) = 0;
// Export a sync fd representing the payload of a semaphore.
virtual bool GetSemaphoreFdKHR(VkDevice vk_device,
VkSemaphore vk_semaphore,
base::ScopedFD* sync_fd) = 0;
#endif
private:
DISALLOW_COPY_AND_ASSIGN(VulkanImplementation);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment