-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Actually two apps. One app acts as exporter, exporting memory to an opaque fd containing data about its color render target, while the other app acts as importer. The exporter waits for the importer to connect via UNIX domain socket and then it sends the opaque fd. The importer connects to the exporter and retrieves the fd to use for importing memory.
- Loading branch information
1 parent
9943cf4
commit eb82b6b
Showing
6 changed files
with
728 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
############################################################################### | ||
# Copyright (c) 2024 LunarG, Inc. | ||
# All rights reserved | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to | ||
# deal in the Software without restriction, including without limitation the | ||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
# sell copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
# IN THE SOFTWARE. | ||
# | ||
# Author: LunarG Team | ||
# Description: CMake script for VK_KHR_external_memory_fd tests | ||
############################################################################### | ||
|
||
add_subdirectory(export) | ||
add_subdirectory(import) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
############################################################################### | ||
# Copyright (c) 2024 LunarG, Inc. | ||
# All rights reserved | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to | ||
# deal in the Software without restriction, including without limitation the | ||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
# sell copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
# IN THE SOFTWARE. | ||
# | ||
# Author: LunarG Team | ||
# Description: CMake script for VK_KHR_external_memory_fd export test app | ||
############################################################################### | ||
|
||
add_executable(gfxrecon-external-memory-fd-export "") | ||
|
||
target_sources(gfxrecon-external-memory-fd-export | ||
PRIVATE | ||
${CMAKE_CURRENT_LIST_DIR}/app.cpp | ||
${CMAKE_CURRENT_LIST_DIR}/../../common/test_app_base.cpp) | ||
|
||
target_include_directories(gfxrecon-external-memory-fd-export PUBLIC | ||
${CMAKE_BINARY_DIR} | ||
${CMAKE_CURRENT_LIST_DIR}/../../common) | ||
|
||
target_link_libraries(gfxrecon-external-memory-fd-export | ||
gfxrecon_application | ||
gfxrecon_decode | ||
gfxrecon_graphics | ||
gfxrecon_format | ||
gfxrecon_util | ||
SDL3::SDL3 | ||
platform_specific) | ||
|
||
if (MSVC) | ||
# Force inclusion of "gfxrecon_disable_popup_result" variable in linking. | ||
# On 32-bit windows, MSVC prefixes symbols with "_" but on 64-bit windows it doesn't. | ||
if(CMAKE_SIZEOF_VOID_P EQUAL 4) | ||
target_link_options(gfxrecon-replay PUBLIC "LINKER:/Include:_gfxrecon_disable_popup_result") | ||
else() | ||
target_link_options(gfxrecon-replay PUBLIC "LINKER:/Include:gfxrecon_disable_popup_result") | ||
endif() | ||
endif() | ||
|
||
common_build_directives(gfxrecon-external-memory-fd-export) | ||
|
||
add_custom_command( | ||
TARGET gfxrecon-external-memory-fd-export | ||
POST_BUILD | ||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}) | ||
if (WIN32) | ||
add_custom_command(TARGET gfxrecon-external-memory-fd-export POST_BUILD | ||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:gfxrecon-external-memory-fd-export> $<TARGET_FILE_DIR:gfxrecon-external-memory-fd-export> | ||
COMMAND_EXPAND_LISTS) | ||
endif () | ||
|
||
install(TARGETS gfxrecon-external-memory-fd-export RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | ||
|
||
add_dependencies(gfxrecon-testapps gfxrecon-external-memory-fd-export) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
/* | ||
** Copyright (c) 2024 LunarG, Inc. | ||
** | ||
** Permission is hereby granted, free of charge, to any person obtaining a | ||
** copy of this software and associated documentation files (the "Software"), | ||
** to deal in the Software without restriction, including without limitation | ||
** the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
** and/or sell copies of the Software, and to permit persons to whom the | ||
** Software is furnished to do so, subject to the following conditions: | ||
** | ||
** The above copyright notice and this permission notice shall be included in | ||
** all copies or substantial portions of the Software. | ||
** | ||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
** DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
#include <fcntl.h> | ||
#include <sys/socket.h> | ||
#include <sys/un.h> | ||
#include <unistd.h> | ||
|
||
#include <iostream> | ||
|
||
#include <vulkan/vulkan_core.h> | ||
|
||
#include <util/logging.h> | ||
|
||
#include <test_app_base.h> | ||
|
||
#ifdef __linux__ | ||
#define HAVE_MSGHDR_MSG_CONTROL | ||
#endif | ||
|
||
GFXRECON_BEGIN_NAMESPACE(gfxrecon) | ||
|
||
GFXRECON_BEGIN_NAMESPACE(test_app) | ||
|
||
GFXRECON_BEGIN_NAMESPACE(external_memory_fd_export) | ||
|
||
class App : public gfxrecon::test::TestAppBase | ||
{ | ||
public: | ||
App() = default; | ||
virtual ~App() = default; | ||
App(const App&) = delete; | ||
App& operator=(const App&) = delete; | ||
App(App&&) = delete; | ||
App& operator=(App&&) = delete; | ||
|
||
private: | ||
const uint32_t buffer_size_ = sizeof(uint32_t[42]); | ||
VkBuffer buffer_ = VK_NULL_HANDLE; | ||
VkDeviceMemory exportable_memory_ = VK_NULL_HANDLE; | ||
|
||
void configure_instance_builder(test::InstanceBuilder& instance_builder) override; | ||
void configure_physical_device_selector(test::PhysicalDeviceSelector& phys_device_selector) override; | ||
|
||
uint32_t find_memory_type(uint32_t memoryTypeBits, VkMemoryPropertyFlags memory_property_flags); | ||
void create_buffer(); | ||
|
||
int get_exportable_fd(); | ||
void send_exportable_fd(int exportable_fd); | ||
ssize_t send_int(int conn_fd, int data); | ||
|
||
void cleanup() override; | ||
bool frame(const int frame_num) override; | ||
void setup() override; | ||
}; | ||
|
||
void App::configure_instance_builder(test::InstanceBuilder& instance_builder) | ||
{ | ||
instance_builder.enable_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); | ||
instance_builder.set_headless(true); | ||
} | ||
|
||
void App::configure_physical_device_selector(test::PhysicalDeviceSelector& phys_device_selector) | ||
{ | ||
phys_device_selector.add_required_extension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); | ||
phys_device_selector.add_required_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); | ||
} | ||
|
||
uint32_t App::find_memory_type(uint32_t memoryTypeBits, VkMemoryPropertyFlags memory_property_flags) | ||
{ | ||
VkPhysicalDeviceMemoryProperties memory_properties; | ||
init.inst_disp.getPhysicalDeviceMemoryProperties(init.physical_device, &memory_properties); | ||
|
||
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i) | ||
{ | ||
if ((memoryTypeBits & (1 << i)) && (memory_properties.memoryTypes[i].propertyFlags & memory_property_flags) > 0) | ||
{ | ||
return i; | ||
break; | ||
} | ||
} | ||
|
||
throw std::runtime_error("Could not find required memory type"); | ||
} | ||
|
||
void App::create_buffer() | ||
{ | ||
VkExternalMemoryBufferCreateInfo external_mem_buf_create_info = {}; | ||
external_mem_buf_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; | ||
external_mem_buf_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | ||
|
||
VkBufferCreateInfo buffer_create_info = {}; | ||
buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | ||
buffer_create_info.pNext = &external_mem_buf_create_info; | ||
buffer_create_info.flags = 0u; | ||
buffer_create_info.size = buffer_size_; | ||
buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; | ||
buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||
buffer_create_info.queueFamilyIndexCount = 0u; | ||
buffer_create_info.pQueueFamilyIndices = nullptr; | ||
VkResult result = init.disp.createBuffer(&buffer_create_info, nullptr, &buffer_); | ||
VERIFY_VK_RESULT("Failed to create buffer", result); | ||
|
||
VkMemoryRequirements buf_mem_requirements; | ||
init.disp.getBufferMemoryRequirements(buffer_, &buf_mem_requirements); | ||
|
||
VkExportMemoryAllocateInfo export_mem_alloc_info = {}; | ||
export_mem_alloc_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; | ||
export_mem_alloc_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | ||
|
||
VkMemoryAllocateInfo buf_mem_allocate_info; | ||
buf_mem_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | ||
buf_mem_allocate_info.pNext = &export_mem_alloc_info; | ||
buf_mem_allocate_info.allocationSize = buf_mem_requirements.size; | ||
buf_mem_allocate_info.memoryTypeIndex = | ||
find_memory_type(buf_mem_requirements.memoryTypeBits, | ||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); | ||
result = init.disp.allocateMemory(&buf_mem_allocate_info, nullptr, &exportable_memory_); | ||
VERIFY_VK_RESULT("Failed to exportable memory", result); | ||
|
||
result = init.disp.bindBufferMemory(buffer_, exportable_memory_, 0u); | ||
VERIFY_VK_RESULT("Failed to bind memory", result); | ||
|
||
uint32_t* data = nullptr; | ||
result = init.disp.mapMemory(exportable_memory_, 0u, buffer_size_, 0u, reinterpret_cast<void**>(&data)); | ||
VERIFY_VK_RESULT("Failed to map buffer memory", result); | ||
for (uint32_t i = 0; i < buffer_size_ / sizeof(uint32_t); ++i) | ||
{ | ||
data[i] = i; | ||
} | ||
|
||
init.disp.unmapMemory(exportable_memory_); | ||
} | ||
|
||
int App::get_exportable_fd() | ||
{ | ||
VkMemoryGetFdInfoKHR get_fd_info = {}; | ||
get_fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR; | ||
get_fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; | ||
get_fd_info.memory = exportable_memory_; | ||
|
||
int exportable_fd = -1; | ||
VkResult result = init.disp.getMemoryFdKHR(&get_fd_info, &exportable_fd); | ||
VERIFY_VK_RESULT("Failed to get memory fd", result); | ||
return exportable_fd; | ||
} | ||
|
||
void App::send_exportable_fd(int exportable_fd) | ||
{ | ||
// Need to send the fd to the importer process | ||
int external_socket = socket(PF_UNIX, SOCK_STREAM, 0); | ||
GFXRECON_ASSERT(external_socket >= 0) | ||
sockaddr_un un = {}; | ||
un.sun_family = AF_UNIX; | ||
|
||
const char* socket_name = "/tmp/.external-memory"; | ||
snprintf(un.sun_path, sizeof(un.sun_path), "%s", socket_name); | ||
unlink(un.sun_path); | ||
|
||
int bind_result = bind(external_socket, reinterpret_cast<struct sockaddr*>(&un), sizeof(un)); | ||
GFXRECON_ASSERT(bind_result >= 0) | ||
|
||
int listen_result = listen(external_socket, 1); | ||
GFXRECON_ASSERT(listen_result >= 0) | ||
|
||
GFXRECON_LOG_INFO("Waiting for importer to connect"); | ||
// Blocking | ||
int conn_fd = accept(external_socket, nullptr, nullptr); | ||
GFXRECON_ASSERT(conn_fd >= 0) | ||
|
||
// Send fd | ||
ssize_t send_result = send_int(conn_fd, exportable_fd); | ||
GFXRECON_ASSERT(send_result >= 0); | ||
|
||
close(conn_fd); | ||
close(external_socket); | ||
} | ||
|
||
ssize_t App::send_int(int conn_fd, int data) | ||
{ | ||
struct msghdr msg = {}; | ||
struct iovec iov[1]; | ||
|
||
#ifdef HAVE_MSGHDR_MSG_CONTROL | ||
union | ||
{ | ||
struct cmsghdr cm; | ||
char control[CMSG_SPACE(sizeof(int))]; | ||
} control_un = {}; | ||
|
||
msg.msg_control = control_un.control; | ||
msg.msg_controllen = sizeof(control_un.control); | ||
|
||
struct cmsghdr* cmptr = CMSG_FIRSTHDR(&msg); | ||
cmptr->cmsg_len = CMSG_LEN(sizeof(int)); | ||
cmptr->cmsg_level = SOL_SOCKET; | ||
cmptr->cmsg_type = SCM_RIGHTS; | ||
*reinterpret_cast<int*>(CMSG_DATA(cmptr)) = data; | ||
#else | ||
msg.msg_accrights = (caddr_t)&data; | ||
msg.msg_accrightslen = sizeof(int); | ||
#endif | ||
|
||
msg.msg_name = NULL; | ||
msg.msg_namelen = 0; | ||
|
||
char c[] = "1"; | ||
iov[0].iov_base = c; | ||
iov[0].iov_len = 1; | ||
msg.msg_iov = iov; | ||
msg.msg_iovlen = 1; | ||
|
||
return sendmsg(conn_fd, &msg, 0); | ||
} | ||
|
||
bool App::frame(const int frame_num) | ||
{ | ||
return false; | ||
} | ||
|
||
void App::cleanup() | ||
{ | ||
init.disp.destroyBuffer(buffer_, nullptr); | ||
init.disp.freeMemory(exportable_memory_, nullptr); | ||
} | ||
|
||
void App::setup() | ||
{ | ||
create_buffer(); | ||
int fd = get_exportable_fd(); | ||
GFXRECON_LOG_INFO("Exporting fd (%d)", fd); | ||
send_exportable_fd(fd); | ||
GFXRECON_LOG_INFO("Bye"); | ||
} | ||
|
||
GFXRECON_END_NAMESPACE(external_memory_fd_export) | ||
|
||
GFXRECON_END_NAMESPACE(test_app) | ||
|
||
GFXRECON_END_NAMESPACE(gfxrecon) | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
try | ||
{ | ||
gfxrecon::test_app::external_memory_fd_export::App app; | ||
app.run("external memory fd export"); | ||
return 0; | ||
} | ||
catch (const std::exception& e) | ||
{ | ||
std::cerr << e.what() << std::endl; | ||
return -1; | ||
} | ||
} |
Oops, something went wrong.