Skip to content

ludus::graphics::rhi::HostedSurfaceConsumer

Ludus Wiki · API overview · Browse API

Class

Imports a hosted game's surface onto the editor's GPU device.
Start() borrows a started HostedWindowEndpoint and the editor's own device. Pump() takes the endpoint's surface events: it imports each new generation and records completed frames. AcquireFrame() returns the newest completed frame; frames superseded before they were acquired are returned to the game at once. ReleaseFrame() returns a frame after the editor's sampling has completed, or ReleaseFrameAfterQueue() returns it once the editor's queue has finished that sampling, and a replaced generation is destroyed once none of its frames is held.
Completion is fenced on the CPU: the game announces a frame only after its GPU work completed, so a frame needs no wait before sampling; and the editor must release it only after its own GPU work that sampled it has completed. Neither side shares fence objects. The consumer itself submits whatever its backend needs on the identity's queue around that sampling (Vulkan's queue family transfers), so callers record nothing backend-specific.
  • macOS: the images are IOSurfaces received as Mach send rights through the session's Mach rendezvous; the consumer creates its textures on the given id<MTLDevice>. IOSurfaces work across GPUs, so there is no adapter check.
  • Linux: the images are Vulkan memory exported as opaque file descriptors (VK_KHR_external_memory_fd). They import only when the game's deviceUUID and driverUUID equal the consumer's; otherwise the consumer refuses with AdapterMismatch. The consumer device must have been created with VK_KHR_external_memory_fd enabled, on Vulkan 1.1 or later.
Qt-free and not synchronized: use it on the thread that owns the device and pumps the endpoint. The endpoint and the device must outlive Stop().

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

#include <ludus/graphics/rhi/hosted_surface.h>
class ludus::graphics::rhi::HostedSurfaceConsumer final

Methods

HostedSurfaceConsumer

ludus::graphics::rhi::HostedSurfaceConsumer::HostedSurfaceConsumer() noexcept
Construct a stopped consumer. Does not allocate.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

~HostedSurfaceConsumer

ludus::graphics::rhi::HostedSurfaceConsumer::~HostedSurfaceConsumer() noexcept
Stop(); the caller must already have completed GPU work that samples held frames.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

HostedSurfaceConsumer

ludus::graphics::rhi::HostedSurfaceConsumer::HostedSurfaceConsumer(const HostedSurfaceConsumer &)=delete
Not copyable: one consumer owns the imported images.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

operator=

HostedSurfaceConsumer & ludus::graphics::rhi::HostedSurfaceConsumer::operator=(const HostedSurfaceConsumer &)=delete
Not copyable: one consumer owns the imported images.

Related types: HostedSurfaceConsumer

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

HostedSurfaceConsumer

ludus::graphics::rhi::HostedSurfaceConsumer::HostedSurfaceConsumer(HostedSurfaceConsumer &&)=delete
Not movable: frames refer to the consumer that holds them.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

operator=

HostedSurfaceConsumer & ludus::graphics::rhi::HostedSurfaceConsumer::operator=(HostedSurfaceConsumer &&)=delete
Not movable: frames refer to the consumer that holds them.

Related types: HostedSurfaceConsumer

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

Start

HostedConsumerStatus ludus::graphics::rhi::HostedSurfaceConsumer::Start(platform::HostedWindowEndpoint &inoutEndpoint, const NativeDeviceIdentity &device) noexcept
Start importing the surface of the window admitted by endpoint.
ParameterDescription
inoutEndpoint
Started endpoint, borrowed until Stop(); the consumer takes its surface events and sends releases through it. The caller keeps pumping it.
device
The consumer's device. Metal: Api Metal and Device an id<MTLDevice>. Vulkan: Api Vulkan with Instance, PhysicalDevice, Device, CommandQueue and its QueueFamily; the instance must use Vulkan 1.1 or later. The consumer submits its queue family transfers and release fences to that queue.

Returns

Ok; InvalidState when already started; InvalidArgument for an incomplete identity or an API without a hosted import in this build; Unavailable when the target has no hosted surface, the device's entry points cannot be loaded or allocation failed.

Related types: platform::HostedWindowEndpoint · HostedConsumerStatus · NativeDeviceIdentity

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

Stop

void ludus::graphics::rhi::HostedSurfaceConsumer::Stop() noexcept
Destroy every imported image and forget held frames.

Precondition

GPU work that samples any held frame has completed.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

Pump

HostedConsumerStatus ludus::graphics::rhi::HostedSurfaceConsumer::Pump() noexcept
Import new generations and record completed frames from the endpoint.
Call after HostedWindowEndpoint::Pump(), once per editor frame.

Returns

Ok; Refused once the game's images were refused; NotConnected while no window is connected (not yet admitted, or gone); InvalidState when stopped.

Related types: HostedConsumerStatus

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

HasFrame

bool ludus::graphics::rhi::HostedSurfaceConsumer::HasFrame() const noexcept
True when a completed frame newer than every acquired frame is waiting.

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

AcquireFrame

HostedConsumerStatus ludus::graphics::rhi::HostedSurfaceConsumer::AcquireFrame(HostedFrame &outFrame) noexcept
Take the newest completed frame.
The consumer holds it until ReleaseFrame(). Several frames may be held at once, for example one on screen and one pending; the game renders into the rest. On Vulkan this submits the second half of the game's queue family transfer to the identity's queue, so sampling submitted there afterwards needs no barrier; call it on the thread that submits to that queue, between its submissions.
ParameterDescription
outFrame
The frame; unchanged unless Ok.

Returns

Ok, Empty, Refused or InvalidState; Unavailable when the transfer could not be submitted, in which case the frame went back to the game unseen.

Related types: HostedConsumerStatus · HostedFrame

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

ReleaseFrame

HostedConsumerStatus ludus::graphics::rhi::HostedSurfaceConsumer::ReleaseFrame(const HostedFrame &frame) noexcept
Return a held frame to the game.
Submits nothing: the game discards the image's contents before it renders into it again, so the image needs no queue family release once its sampling has completed.

Precondition

The work submitted to the identity's queue up to the consumer's last sampling of the frame has completed (on Vulkan this includes the transfer AcquireFrame() submitted).
ParameterDescription
frame
A frame from AcquireFrame() that is still held.

Returns

Ok (also when the window has gone; the frame is forgotten); InvalidState for a frame this consumer does not hold.

Related types: HostedConsumerStatus · HostedFrame

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

ReleaseFrameAfterQueue

HostedConsumerStatus ludus::graphics::rhi::HostedSurfaceConsumer::ReleaseFrameAfterQueue(const HostedFrame &frame) noexcept
Return a held frame once the consumer's queue has finished the work already submitted to it.
Commits a completion marker on the device identity's CommandQueue, behind the editor's sampling of the frame; a later Pump() returns the image to the game once the marker completes. Metal commits an empty command buffer. Vulkan submits the image's release to the external queue family with a fence, which signals once all work submitted to the queue before it has completed. Call it right after the sampling work was submitted, for example after Qt's afterFrameEnd, on the thread that submits to that queue. No CPU wait.
ParameterDescription
frame
A frame from AcquireFrame() that is still held and not already queued.

Returns

Ok; InvalidState for a frame not held or already queued; Unavailable when the marker could not be committed (Metal: no CommandQueue in the identity), in which case the frame stays held.

Related types: HostedConsumerStatus · HostedFrame

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

GetQueuedReleaseCount

foundation::usize ludus::graphics::rhi::HostedSurfaceConsumer::GetQueuedReleaseCount() const noexcept
Frames queued by ReleaseFrameAfterQueue() whose marker has not completed yet.

Related types: foundation::usize

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

GetRefusal

HostedConsumerRefusal ludus::graphics::rhi::HostedSurfaceConsumer::GetRefusal() const noexcept
Why the consumer refused the game's images, or None.

Related types: HostedConsumerRefusal

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h

GetImportedGenerationCount

foundation::usize ludus::graphics::rhi::HostedSurfaceConsumer::GetImportedGenerationCount() const noexcept
Generations with imported images, the newest and those still held.

Related types: foundation::usize

Declared in modules/graphics/rhi/include/ludus/graphics/rhi/hosted_surface.h