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) { ...@@ -52,11 +52,15 @@ if (enable_vulkan) {
"viz_vulkan_context_provider_export.h", "viz_vulkan_context_provider_export.h",
] ]
configs = [ "//third_party/vulkan:vulkan_config" ] configs = [ "//third_party/vulkan:vulkan_config" ]
public_deps = [
"//skia",
]
deps = [ deps = [
"//base", "//base",
"//gpu/vulkan", "//gpu/vulkan",
"//gpu/vulkan:buildflags", "//gpu/vulkan:buildflags",
"//skia",
] ]
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import("//build/config/ui.gni") import("//build/config/ui.gni")
import("//gpu/vulkan/features.gni") import("//gpu/vulkan/features.gni")
import("//testing/test.gni")
assert(enable_vulkan) assert(enable_vulkan)
assert(is_android) assert(is_android)
...@@ -22,7 +23,9 @@ component("android") { ...@@ -22,7 +23,9 @@ component("android") {
defines = [ "IS_VULKAN_ANDROID_IMPL" ] defines = [ "IS_VULKAN_ANDROID_IMPL" ]
deps = [ "//ui/gfx" ] deps = [
"//ui/gfx",
]
public_configs = [ ":vulkan_android" ] public_configs = [ ":vulkan_android" ]
...@@ -31,3 +34,17 @@ component("android") { ...@@ -31,3 +34,17 @@ component("android") {
"//gpu/vulkan", "//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 @@ ...@@ -6,6 +6,7 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h" #include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_instance.h" #include "gpu/vulkan/vulkan_instance.h"
#include "gpu/vulkan/vulkan_surface.h" #include "gpu/vulkan/vulkan_surface.h"
...@@ -19,7 +20,10 @@ VulkanImplementationAndroid::~VulkanImplementationAndroid() = default; ...@@ -19,7 +20,10 @@ VulkanImplementationAndroid::~VulkanImplementationAndroid() = default;
bool VulkanImplementationAndroid::InitializeVulkanInstance() { bool VulkanImplementationAndroid::InitializeVulkanInstance() {
std::vector<const char*> required_extensions = { 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 = VulkanFunctionPointers* vulkan_function_pointers =
gpu::GetVulkanFunctionPointers(); gpu::GetVulkanFunctionPointers();
...@@ -80,7 +84,9 @@ bool VulkanImplementationAndroid::GetPhysicalDevicePresentationSupport( ...@@ -80,7 +84,9 @@ bool VulkanImplementationAndroid::GetPhysicalDevicePresentationSupport(
std::vector<const char*> std::vector<const char*>
VulkanImplementationAndroid::GetRequiredDeviceExtensions() { 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( VkFence VulkanImplementationAndroid::CreateVkFenceForGpuFence(
...@@ -96,4 +102,65 @@ VulkanImplementationAndroid::ExportVkFenceToGpuFence(VkDevice vk_device, ...@@ -96,4 +102,65 @@ VulkanImplementationAndroid::ExportVkFenceToGpuFence(VkDevice vk_device,
return nullptr; 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 } // namespace gpu
...@@ -34,6 +34,12 @@ class COMPONENT_EXPORT(VULKAN_ANDROID) VulkanImplementationAndroid ...@@ -34,6 +34,12 @@ class COMPONENT_EXPORT(VULKAN_ANDROID) VulkanImplementationAndroid
std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence( std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(
VkDevice vk_device, VkDevice vk_device,
VkFence vk_fence) override; 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: private:
VulkanInstance vulkan_instance_; VulkanInstance vulkan_instance_;
......
...@@ -61,6 +61,7 @@ VULKAN_DEVICE_FUNCTIONS = [ ...@@ -61,6 +61,7 @@ VULKAN_DEVICE_FUNCTIONS = [
{ 'name': 'vkDestroySampler' }, { 'name': 'vkDestroySampler' },
{ 'name': 'vkDestroySemaphore' }, { 'name': 'vkDestroySemaphore' },
{ 'name': 'vkDestroyShaderModule' }, { 'name': 'vkDestroyShaderModule' },
{ 'name': 'vkDeviceWaitIdle' },
{ 'name': 'vkFreeCommandBuffers' }, { 'name': 'vkFreeCommandBuffers' },
{ 'name': 'vkFreeDescriptorSets' }, { 'name': 'vkFreeDescriptorSets' },
{ 'name': 'vkFreeMemory' }, { 'name': 'vkFreeMemory' },
......
...@@ -223,6 +223,11 @@ bool VulkanFunctionPointers::BindDeviceFunctionPointers(VkDevice vk_device) { ...@@ -223,6 +223,11 @@ bool VulkanFunctionPointers::BindDeviceFunctionPointers(VkDevice vk_device) {
if (!vkDestroyShaderModuleFn) if (!vkDestroyShaderModuleFn)
return false; return false;
vkDeviceWaitIdleFn = reinterpret_cast<PFN_vkDeviceWaitIdle>(
vkGetDeviceProcAddrFn(vk_device, "vkDeviceWaitIdle"));
if (!vkDeviceWaitIdleFn)
return false;
vkFreeCommandBuffersFn = reinterpret_cast<PFN_vkFreeCommandBuffers>( vkFreeCommandBuffersFn = reinterpret_cast<PFN_vkFreeCommandBuffers>(
vkGetDeviceProcAddrFn(vk_device, "vkFreeCommandBuffers")); vkGetDeviceProcAddrFn(vk_device, "vkFreeCommandBuffers"));
if (!vkFreeCommandBuffersFn) if (!vkFreeCommandBuffersFn)
......
...@@ -91,6 +91,7 @@ struct VulkanFunctionPointers { ...@@ -91,6 +91,7 @@ struct VulkanFunctionPointers {
PFN_vkDestroySampler vkDestroySamplerFn = nullptr; PFN_vkDestroySampler vkDestroySamplerFn = nullptr;
PFN_vkDestroySemaphore vkDestroySemaphoreFn = nullptr; PFN_vkDestroySemaphore vkDestroySemaphoreFn = nullptr;
PFN_vkDestroyShaderModule vkDestroyShaderModuleFn = nullptr; PFN_vkDestroyShaderModule vkDestroyShaderModuleFn = nullptr;
PFN_vkDeviceWaitIdle vkDeviceWaitIdleFn = nullptr;
PFN_vkFreeCommandBuffers vkFreeCommandBuffersFn = nullptr; PFN_vkFreeCommandBuffers vkFreeCommandBuffersFn = nullptr;
PFN_vkFreeDescriptorSets vkFreeDescriptorSetsFn = nullptr; PFN_vkFreeDescriptorSets vkFreeDescriptorSetsFn = nullptr;
PFN_vkFreeMemory vkFreeMemoryFn = nullptr; PFN_vkFreeMemory vkFreeMemoryFn = nullptr;
...@@ -202,6 +203,7 @@ struct VulkanFunctionPointers { ...@@ -202,6 +203,7 @@ struct VulkanFunctionPointers {
gpu::GetVulkanFunctionPointers()->vkDestroySemaphoreFn gpu::GetVulkanFunctionPointers()->vkDestroySemaphoreFn
#define vkDestroyShaderModule \ #define vkDestroyShaderModule \
gpu::GetVulkanFunctionPointers()->vkDestroyShaderModuleFn gpu::GetVulkanFunctionPointers()->vkDestroyShaderModuleFn
#define vkDeviceWaitIdle gpu::GetVulkanFunctionPointers()->vkDeviceWaitIdleFn
#define vkFreeCommandBuffers \ #define vkFreeCommandBuffers \
gpu::GetVulkanFunctionPointers()->vkFreeCommandBuffersFn gpu::GetVulkanFunctionPointers()->vkFreeCommandBuffersFn
#define vkFreeDescriptorSets \ #define vkFreeDescriptorSets \
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <memory> #include <memory>
#include "base/files/scoped_file.h"
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h"
#include "gpu/vulkan/vulkan_export.h" #include "gpu/vulkan/vulkan_export.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -53,6 +55,22 @@ class VULKAN_EXPORT VulkanImplementation { ...@@ -53,6 +55,22 @@ class VULKAN_EXPORT VulkanImplementation {
VkDevice vk_device, VkDevice vk_device,
VkFence vk_fence) = 0; 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: private:
DISALLOW_COPY_AND_ASSIGN(VulkanImplementation); 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