mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 09:00:28 +02:00
aurora: add asynchronous OpenXR stereo replay bridge
This commit is contained in:
1 parent
8c8e4561e9
commit
d8788de919
17 files changed
+1521
-74
No files matched your search
@@ -82,14 +82,17 @@ enum { AURORA_STEREO_EYE_COUNT = 2 };
|
||||
/**
|
||||
* One eye of a stereo frame supplied by the host application.
|
||||
*
|
||||
* projection is a row-major, renderer-ready 4x4 projection matrix. It uses
|
||||
* the same convention as the matrix uploaded by GXSetProjection after
|
||||
* Aurora's depth-range adjustment.
|
||||
* projection is row-major and supplies the OpenXR frustum's X/Y scale and
|
||||
* asymmetric-center terms at [0][0], [0][2], [1][1], and [1][2]. Aurora
|
||||
* applies those four values to each perspective GX draw while preserving the
|
||||
* draw's own depth mapping and renderer depth-range adjustment.
|
||||
*
|
||||
* viewFromCenter is a row-major affine 3x4 transform from the game's
|
||||
* recorded center-eye view space into this eye's view space. Identity keeps
|
||||
* the recorded view and is useful when the game has already applied the eye
|
||||
* transform before issuing GX commands.
|
||||
*
|
||||
* Both transforms are ignored in AURORA_STEREO_FRAME_VIRTUAL_SCREEN mode.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
@@ -98,13 +101,30 @@ typedef struct {
|
||||
float viewFromCenter[12];
|
||||
} AuroraStereoEye;
|
||||
|
||||
typedef enum {
|
||||
// Replay perspective GX draws with the supplied per-eye transforms.
|
||||
AURORA_STEREO_FRAME_IMMERSIVE_REPLAY = 0,
|
||||
// Copy the completed mono present source to both eye outputs. The OpenXR
|
||||
// backend can present these images as a compositor quad layer.
|
||||
AURORA_STEREO_FRAME_VIRTUAL_SCREEN = 1,
|
||||
} AuroraStereoFrameMode;
|
||||
|
||||
// aurora_end_frame() uses this sentinel when its caller cannot associate a
|
||||
// sealed frame with an application safety state. Immersive providers are only
|
||||
// accepted through aurora_end_frame_tagged() with an exact matching tag.
|
||||
#define AURORA_STEREO_CONTENT_TAG_UNKNOWN UINT64_MAX
|
||||
|
||||
/**
|
||||
* Stereo data for one sealed GX frame. frameToken is opaque to Aurora and is
|
||||
* forwarded unchanged to the internal stereo output sink.
|
||||
* forwarded unchanged to the internal stereo output sink. contentTag must
|
||||
* match the tag latched by aurora_end_frame_tagged() for immersive replay.
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t frameToken;
|
||||
AuroraStereoEye eyes[AURORA_STEREO_EYE_COUNT];
|
||||
// Appended to preserve the frameToken/eyes prefix used by older providers.
|
||||
AuroraStereoFrameMode mode;
|
||||
uint64_t contentTag;
|
||||
} AuroraStereoFrame;
|
||||
|
||||
/**
|
||||
@@ -186,6 +206,9 @@ void aurora_shutdown();
|
||||
const AuroraEvent* aurora_update();
|
||||
bool aurora_begin_frame();
|
||||
void aurora_end_frame();
|
||||
// Seal the current frame with an opaque application safety tag. Aurora rejects
|
||||
// an immersive provider packet unless its contentTag matches this exact frame.
|
||||
void aurora_end_frame_tagged(uint64_t contentTag);
|
||||
typedef void (*AuroraFrameWorkerWaitCallback)();
|
||||
// Called from the producer thread at bounded intervals while Aurora waits for
|
||||
// the asynchronous frame worker. The callback must not enter Aurora.
|
||||
@@ -195,6 +218,11 @@ void aurora_set_frame_worker_wait_callback(AuroraFrameWorkerWaitCallback callbac
|
||||
void aurora_set_stereo_frame_provider(AuroraStereoFrameProvider provider, void* userdata);
|
||||
void aurora_wait_for_frame_worker();
|
||||
bool aurora_wait_for_frame_worker_for(uint32_t timeoutMicros);
|
||||
// Producer-thread shutdown barrier. If an asynchronous cycle is waiting for
|
||||
// the next begin-frame permission, grant that permission and wait until the
|
||||
// worker is fully done. Unlike aurora_wait_for_frame_worker(), this is safe in
|
||||
// the gap between aurora_end_frame() and aurora_begin_frame().
|
||||
void aurora_quiesce_frame_worker();
|
||||
// Absolute schedule for the next sealed frame, on steady_clock: baseNanos anchors the group and
|
||||
// intervalNanos is the period, so slot k of N+1 fires at base + k*interval/(N+1). Zeros clear it.
|
||||
void aurora_set_present_schedule(uint64_t baseNanos, uint64_t intervalNanos);
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef AURORA_D3D12_INTEROP_H
|
||||
#define AURORA_D3D12_INTEROP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#else
|
||||
#include "stdbool.h"
|
||||
#include "stdint.h"
|
||||
#endif
|
||||
|
||||
enum { AURORA_D3D12_STEREO_MAX_TARGETS = 2 };
|
||||
|
||||
/**
|
||||
* Borrowed native objects owned by Aurora/Dawn. They remain valid until
|
||||
* aurora_shutdown() and must not be released by the caller.
|
||||
*
|
||||
* colorDxgiFormat is the DXGI format matching Aurora's single-sample eye
|
||||
* output. adapterLuid is returned in the same split representation used by
|
||||
* OpenXR's XrGraphicsRequirementsD3D12KHR.
|
||||
*/
|
||||
typedef struct {
|
||||
void* device;
|
||||
void* queue;
|
||||
int64_t colorDxgiFormat;
|
||||
uint32_t adapterLuidLow;
|
||||
int32_t adapterLuidHigh;
|
||||
} AuroraD3D12NativeHandles;
|
||||
|
||||
/** One acquired OpenXR swapchain image for the next Aurora stereo sink. */
|
||||
typedef struct {
|
||||
void* resource;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int64_t dxgiFormat;
|
||||
} AuroraD3D12StereoTarget;
|
||||
|
||||
/**
|
||||
* Fired when Aurora either finishes or abandons the stereo sink. `success`
|
||||
* guarantees that the final same-queue D3D12 copy and its completion fence were
|
||||
* enqueued. A false result may occur after ExecuteCommandLists, so callers must
|
||||
* conservatively retain externally owned targets until graphics/session
|
||||
* teardown. The callback must not wait for the GPU or re-enter Aurora.
|
||||
*/
|
||||
typedef void (*AuroraD3D12StereoSubmittedCallback)(uint64_t frameToken, bool success,
|
||||
void* userdata);
|
||||
|
||||
/** Returns false unless the active Aurora backend is Dawn D3D12. */
|
||||
bool aurora_d3d12_get_native_handles(AuroraD3D12NativeHandles* handles);
|
||||
|
||||
/**
|
||||
* Installs the internal zero-readback stereo sink. Call while Aurora's frame
|
||||
* worker is idle, after aurora_initialize().
|
||||
*/
|
||||
bool aurora_d3d12_enable_stereo_bridge(AuroraD3D12StereoSubmittedCallback submitted,
|
||||
void* userdata);
|
||||
|
||||
/**
|
||||
* Publishes the acquired OpenXR image(s) for frameToken. Immersive projection
|
||||
* frames supply two targets; virtual-screen quad frames supply one. Exactly
|
||||
* one frame may be pending at a time.
|
||||
*/
|
||||
bool aurora_d3d12_set_stereo_targets(uint64_t frameToken,
|
||||
const AuroraD3D12StereoTarget* targets,
|
||||
uint32_t targetCount);
|
||||
|
||||
/**
|
||||
* Withdraws frameToken only while its target has not been encoded. This is
|
||||
* safe to race with Aurora's frame worker: false means the worker already owns
|
||||
* encoded work (or the token is no longer pending), so the submitted callback
|
||||
* remains the only completion authority. A successful cancellation performs
|
||||
* no GPU work and deliberately does not fire the callback.
|
||||
*/
|
||||
bool aurora_d3d12_cancel_stereo_targets(uint64_t frameToken);
|
||||
|
||||
/**
|
||||
* Removes the sink and drains bridge resources. The worker must be idle. Returns
|
||||
* false when queued work cannot be fenced; in that case the bridge is retained
|
||||
* for the process lifetime and the caller must likewise retain its graphics/XR
|
||||
* owners rather than destroying resources with unknown GPU use.
|
||||
*/
|
||||
bool aurora_d3d12_disable_stereo_bridge();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -82,6 +82,19 @@ uint32_t aurora_get_queued_pipeline_count();
|
||||
void aurora_set_disable_copy_filter(bool disabled);
|
||||
bool aurora_get_disable_copy_filter();
|
||||
|
||||
// Immersive (stereo) replay EFB controls, both enabled by default, and both
|
||||
// live: they take effect on the next frame with no restart.
|
||||
//
|
||||
// stop_at_display_copy ends each eye's replay at the frame's final GXCopyDisp,
|
||||
// so an eye holds exactly the image the game presented. skip_copy_clears drops
|
||||
// the EFB reset a GX copy performs after copying, which on the Wii prepares the
|
||||
// reused EFB for the next frame but on a per-frame eye attachment only erases
|
||||
// the replay. Disable either to compare against the raw replay.
|
||||
void aurora_set_stereo_stop_at_display_copy(bool enabled);
|
||||
bool aurora_get_stereo_stop_at_display_copy();
|
||||
void aurora_set_stereo_skip_copy_clears(bool enabled);
|
||||
bool aurora_get_stereo_skip_copy_clears();
|
||||
|
||||
// Guest-RAM write tracking. `generation` changes whenever guest RAM covering a host range was
|
||||
// written (or returns AURORA_GUEST_WRITE_UNTRACKED); `notify` reports writes aurora made itself.
|
||||
#define AURORA_GUEST_WRITE_UNTRACKED UINT64_MAX
|
||||
|
||||
Reference in new issue
Block a user