doc: Add diagrams for swapchain image allocation control flow.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2300>
This commit is contained in:
Rylie Pavlik 2024-08-02 11:49:38 -05:00
parent cc41c56ad0
commit 0c1f488d8a
7 changed files with 160 additions and 1 deletions

View file

@ -0,0 +1 @@
Illustrate various control flows for swapchain image allocation, including interaction with IPC.

View file

@ -222,7 +222,8 @@ quotas and limits on allocation, etc, the client side allocates the buffer using
a @ref xrt_image_native_allocator (aka XINA) and shares it to the server. When
using D3D11 or D3D12 on Windows, buffers are allocated by the client compositor
and imported into the native compositor, because Vulkan can import buffers from
D3D, but D3D cannot import buffers allocated by Vulkan.
D3D, but D3D cannot import buffers allocated by Vulkan. See @ref swapchains-ipc
for details.
[SCM_RIGHTS]: https://man7.org/linux/man-pages/man3/cmsg.3.html
[win32handles]: https://lackingrhoticity.blogspot.com/2015/05/passing-fds-handles-between-processes.html

View file

@ -0,0 +1,16 @@
%% Copyright 2024, Collabora, Ltd. and the Monado contributors
%% SPDX-License-Identifier: BSL-1.0
%% Simple in-process case
sequenceDiagram
participant app
participant cc as client compositor
participant native_comp as xrt_compositor_native
app->>+cc: xrCreateSwapchain
cc->>+native_comp: xrt_comp_create_swapchain
native_comp->>-cc: xrt_swapchain impl
Note over cc: Keep reference to inner xrt_swapchain in<br>the object we create
Note over cc: Import handles from<br/>inner xrt_swapchain into client API
cc->>-app: return swapchain

View file

@ -0,0 +1,25 @@
%% Copyright 2024, Collabora, Ltd. and the Monado contributors
%% SPDX-License-Identifier: BSL-1.0
%% Out of process, typical behavior (server-side allocation)
sequenceDiagram
box Client Process
participant app
participant cc as client compositor
participant client_native as client process<br/>native compositor<br/>(IPC Stub)
end
box Server Process
participant server_ipc_handler as Server IPC handler
participant server_comp as Server xrt_compositor_native
end
app->>+cc: xrCreateSwapchain
cc->>+client_native: xrt_comp_create_swapchain
client_native->>+server_ipc_handler: xrt_comp_create_swapchain<br/>(IPC call)
server_ipc_handler->>+server_comp: xrt_comp_create_swapchain
server_comp->>-server_ipc_handler: xrt_swapchain impl
server_ipc_handler->>-client_native: swapchain ID and<br/>image handles<br/>(over IPC)
client_native->>-cc: return ipc_swapchain<br/>as inner xrt_swapchain
Note over cc: Keep reference to inner xrt_swapchain in<br>the object we create
Note over cc: Import handles from<br/>inner xrt_swapchain into client API
cc->>-app: return swapchain

View file

@ -0,0 +1,27 @@
%% Copyright 2024, Collabora, Ltd. and the Monado contributors
%% SPDX-License-Identifier: BSL-1.0
%% Out of process, D3D client API
sequenceDiagram
box Client Process
participant app
participant cc as D3D client compositor
participant client_native as client process<br/>native compositor<br/>(IPC Stub)
end
box Server Process
participant server_ipc_handler as Server IPC handler
participant server_comp as Server xrt_compositor_native
end
app->>+cc: xrCreateSwapchain
Note over cc: create images<br/>(because d3d cannot reliably import from Vulkan)
Note over cc: export images to handles
Note over cc: import handles to images for app
cc->>+client_native: xrt_comp_import_swapchain(xrt_image_native[])<br/>(import handles into xrt_swapchain_native)
client_native->>+server_ipc_handler: swapchain_import<br/>(IPC call, copies handles)
server_ipc_handler->>+server_comp: xrt_comp_import_swapchain(xrt_image_native[])
server_comp->>-server_ipc_handler: xrt_swapchain impl
server_ipc_handler->>-client_native: swapchain ID (over IPC)
client_native->>-cc: return ipc_swapchain<br/>as inner xrt_swapchain
Note over cc: Keep reference to inner xrt_swapchain in<br>the object we create
cc->>-app: return swapchain

View file

@ -0,0 +1,28 @@
%% Copyright 2024, Collabora, Ltd. and the Monado contributors
%% SPDX-License-Identifier: BSL-1.0
%% Out of process, with a "xina" in the IPC client (currently only android with AHB)
sequenceDiagram
box Client Process
participant app
participant cc as client compositor
participant client_native as client process<br/>native compositor<br>(IPC Stub)
participant xina as xrt_image_native_allocator
end
box Server Process
participant server_ipc_handler as Server IPC handler
participant server_comp as Server xrt_compositor_native
end
app->>+cc: xrCreateSwapchain
cc->>+client_native: xrt_comp_create_swapchain
client_native->>+xina: create native images
xina->>-client_native: collection of<br/>native image handles
client_native->>+server_ipc_handler: swapchain_import<br/>(IPC call, passing handles)
server_ipc_handler->>+server_comp: xrt_comp_import_swapchain
server_comp->>-server_ipc_handler: xrt_swapchain impl
server_ipc_handler->>-client_native: swapchain ID<br/>(over IPC)
client_native->>-cc: return ipc_swapchain<br>(handles allocated in client process)<br>as inner xrt_swapchain
Note over cc: Keep reference to inner xrt_swapchain in<br>the object we create
Note over cc: Import handles from<br/>inner xrt_swapchain into client API
cc->>-app: return swapchain

61
doc/swapchains-ipc.md Normal file
View file

@ -0,0 +1,61 @@
# Swapchain Allocation and IPC {#swapchains-ipc}
<!--
Copyright 2024, Collabora, Ltd. and the Monado contributors
SPDX-License-Identifier: BSL-1.0
-->
The control flow in Monado for allocating the images/buffers used for a given
@ref XrSwapchain can vary widely based on a number of factors.
## Simple in-process
In the minimal case, which is not common for widespread deployment but which is
useful for debugging, there is only a single process, with the entire runtime
loaded into the "client" application. Despite the absence of IPC in this
scenario, the same basic flow and interaction applies: images are conveyed using
system ("native") handles.
@mermaid{swapchain_allocation_inproc}
The control flow makes its way to the main compositor, which, in default
implementations, uses Vulkan to allocate exportable images.
## Simple out-of-process
The usual model on desktop is that the images for a given @ref XrSwapchain are
allocated in the service, as shown below.
@mermaid{swapchain_allocation_ipc}
However, there are two additional paths possible.
## Client-side Allocation with XINA (Out-of-process)
In some builds, a "XINA" (like the warrior princess) is used: @ref
xrt_image_native_allocator. This allocates the "native" (system handle) images
within the client process, in a central location. Currently only Android builds
using AHardwareBuffer use this model, but ideally we would probably move toward
this model for all systems. The main advantage is that the swapchain images are
allocated in the application process and thus counted against application
quotas, rather than the service/runtime quotas, avoiding security, privacy, and
denial-of-service risks.
@mermaid{swapchain_allocation_ipc_xina}
Generally a XINA used in this way is intended for client-process allocation.
However, there is an implementation (disabled by default) of a "loopback XINA"
in the IPC client, which implements the XINA API using the IPC interface. So
using a XINA in that case would not result in client-process image allocation.
## Allocation for D3D client apps (Out-of-process)
Direct3D cannot reliably and portably import images allocated in Vulkan. So, if
an application uses Direct3D, the D3D client compositor does the allocation, on
the client side, as shown below. The example shown is out-of-process.
@mermaid{swapchain_allocation_ipc_d3d}
Note that this pattern is used even when running in-process with D3D, the result
is a hybrid of this diagram and the first (in-process) diagram, dropping the
client process native compositor and server IPC handler from the diagram.