1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
gpu / vulkan / android / vulkan_android_unittests.cc [blame]
// Copyright 2018 The Chromium Authors
// 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/android/android_hardware_buffer_compat.h"
#include "base/android/scoped_hardware_buffer_handle.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 "gpu/vulkan/vulkan_image.h"
#include "gpu/vulkan/vulkan_util.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_);
// This call checks for all instance extensions. Let the test pass if this
// call fails since many bots would not have this extension present.
if (!vk_implementation_->InitializeVulkanInstance(true /* using_surface */))
return;
// Create vulkan context provider. This call checks for all device
// extensions. Let the test pass if this call fails since many bots would
// not have this extension present.
vk_context_provider_ =
viz::VulkanInProcessContextProvider::Create(vk_implementation_.get());
if (!vk_context_provider_)
return;
// Get the VkDevice.
vk_device_ = vk_context_provider_->GetDeviceQueue()->GetVulkanDevice();
ASSERT_TRUE(vk_device_);
// Get the physical device.
vk_phy_device_ =
vk_context_provider_->GetDeviceQueue()->GetVulkanPhysicalDevice();
ASSERT_TRUE(vk_phy_device_);
}
void TearDown() override {
if (vk_context_provider_)
vk_context_provider_->Destroy();
vk_device_ = VK_NULL_HANDLE;
}
protected:
std::unique_ptr<VulkanImplementation> vk_implementation_;
scoped_refptr<viz::VulkanInProcessContextProvider> vk_context_provider_;
VkDevice vk_device_;
VkPhysicalDevice vk_phy_device_;
};
TEST_F(VulkanImplementationAndroidTest, ExportImportSyncFd) {
if (!vk_implementation_ || !vk_context_provider_)
return;
// 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.
EXPECT_TRUE(SubmitSignalVkSemaphore(
vk_context_provider_->GetDeviceQueue()->GetVulkanQueue(), semaphore1));
// Export a handle from the semaphore.
SemaphoreHandle handle =
vk_implementation_->GetSemaphoreHandle(vk_device_, semaphore1);
EXPECT_TRUE(handle.is_valid());
// Import the above semaphore handle into a new semaphore.
VkSemaphore semaphore2 =
vk_implementation_->ImportSemaphoreHandle(vk_device_, std::move(handle));
EXPECT_NE(semaphore2, static_cast<VkSemaphore>(VK_NULL_HANDLE));
// 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);
}
TEST_F(VulkanImplementationAndroidTest, CreateVkImageFromAHB) {
if (!vk_implementation_ || !vk_context_provider_)
return;
// Setup and Create an AHardwareBuffer.
AHardwareBuffer* buffer = nullptr;
AHardwareBuffer_Desc hwb_desc;
hwb_desc.width = 128;
hwb_desc.height = 128;
hwb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
hwb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
hwb_desc.layers = 1;
hwb_desc.stride = 0;
hwb_desc.rfu0 = 0;
hwb_desc.rfu1 = 0;
// Allocate an AHardwareBuffer.
base::AndroidHardwareBufferCompat::GetInstance().Allocate(&hwb_desc, &buffer);
EXPECT_TRUE(buffer);
// Create a vkimage and import the AHB into it.
const gfx::Size size(hwb_desc.width, hwb_desc.height);
auto* device_queue = vk_context_provider_->GetDeviceQueue();
auto handle = base::android::ScopedHardwareBufferHandle::Adopt(buffer);
gfx::GpuMemoryBufferHandle gmb_handle(std::move(handle));
auto vulkan_image = VulkanImage::CreateFromGpuMemoryBufferHandle(
device_queue, std::move(gmb_handle), size, VK_FORMAT_R8G8B8A8_UNORM,
/*usage=*/0, /*flags=*/0, /*image_tiling=*/VK_IMAGE_TILING_OPTIMAL,
/*queue_family_index=*/VK_QUEUE_FAMILY_EXTERNAL);
EXPECT_TRUE(vulkan_image);
vulkan_image->Destroy();
}
} // namespace gpu