blob: f218c58cb46fa802d0152ac60c76948541ce9387 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 <stdio.h>
#include "platform_event.h"
#define LOG_VERBOSE(msg, ...) \
if (true) \
fprintf(stderr, "%s:%d " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__)
std::unique_ptr<PlatformEvent> LinuxEvent::Duplicate(VkDevice device,
VkLayerDispatchTable* dispatch_table) {
// Export from our fence into newly created fence.
VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
VkFence fence;
VkResult result = dispatch_table->CreateFence(device, &create_info,
nullptr, // pAllocator
&fence);
if (result != VK_SUCCESS) {
LOG_VERBOSE("CreateFence failed: %d", result);
return nullptr;
}
VkFenceGetFdInfoKHR get_fd_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
.pNext = nullptr,
.fence = fence_,
.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
int fd;
result = dispatch_table->GetFenceFdKHR(device, &get_fd_info, &fd);
if (result != VK_SUCCESS) {
LOG_VERBOSE("GetFenceFdKHR failed: %d", result);
dispatch_table->DestroyFence(device, fence,
nullptr // pAllocator
);
return nullptr;
}
// Import to fence
VkImportFenceFdInfoKHR import_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
.pNext = nullptr,
.fence = fence,
.flags = 0,
.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
.fd = fd,
};
result = dispatch_table->ImportFenceFdKHR(device, &import_info);
if (result != VK_SUCCESS) {
LOG_VERBOSE("ImportFenceFdKHR failed: %d", result);
dispatch_table->DestroyFence(device, fence,
nullptr // pAllocator
);
// The fd is left open; TODO(https://fxbug.dev/42146493) close the fd
return nullptr;
}
return std::make_unique<LinuxEvent>(fence);
}
PlatformEvent::WaitResult LinuxEvent::Wait(VkDevice device, VkLayerDispatchTable* dispatch_table,
uint64_t timeout_ns) {
VkResult result = dispatch_table->WaitForFences(device, 1, &fence_, VK_TRUE, timeout_ns);
switch (result) {
case VK_SUCCESS:
return WaitResult::Ok;
case VK_TIMEOUT:
return WaitResult::TimedOut;
default:
LOG_VERBOSE("WaitForFences failed: %d", result);
return WaitResult::Error;
}
}
VkResult LinuxEvent::ImportToSemaphore(VkDevice device, VkLayerDispatchTable* dispatch_table,
VkSemaphore& semaphore_out) {
// Export from fence
VkFenceGetFdInfoKHR get_fd_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
.pNext = nullptr,
.fence = fence_,
.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
int fd = 0;
VkResult result = dispatch_table->GetFenceFdKHR(device, &get_fd_info, &fd);
if (result != VK_SUCCESS) {
LOG_VERBOSE("GetFenceFdKHR failed: %d", result);
return result;
}
// Destroy fence for ownership transfer
dispatch_table->DestroyFence(device, fence_,
nullptr // pAllocator
);
fence_ = VK_NULL_HANDLE;
// Import to semaphore
VkImportSemaphoreFdInfoKHR import_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
.pNext = nullptr,
.semaphore = semaphore_out,
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
.fd = fd,
};
result = dispatch_table->ImportSemaphoreFdKHR(device, &import_info);
if (result != VK_SUCCESS) {
LOG_VERBOSE("ImportSemaphoreFdKHR failed: %d", result);
// The fd is left open; TODO(https://fxbug.dev/42146493) close the fd
return result;
}
return VK_SUCCESS;
}
std::unique_ptr<PlatformEvent> PlatformEvent::Create(VkDevice device,
VkLayerDispatchTable* dispatch_table,
bool signaled) {
VkExportFenceCreateInfo export_create_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
.pNext = nullptr,
.handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
};
VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = &export_create_info,
.flags = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0u,
};
VkFence fence;
VkResult result = dispatch_table->CreateFence(device, &create_info,
nullptr, // pAllocator,
&fence);
if (result != VK_SUCCESS) {
LOG_VERBOSE("CreateFence failed: %d", result);
return nullptr;
}
return std::make_unique<LinuxEvent>(fence);
}