mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 05:00:27 +02:00
The panel was drawn into the eye images, so below a 1.00x OpenXR resolution its 1440x1080 canvas was minified into a small eye region and the text became hard to read. It is now submitted as a quad layer of its own over the scene's projection or menu quad, which the compositor samples directly at any render scale. Each backend (D3D12, Windows Vulkan, Quest) makes the panel's swapchain pair (plus two shared buffers on the Quest) the first time the panel opens. While it is open, the frame hands Aurora one more stereo target after the eyes, which the bridge fills with the panel texture or a transparent image. The panel image follows the eyes' displayed/retained pairing, so a cancelled frame never shows an unwritten panel. The quad hangs where the pointer's hits are tested. Aurora leaves the panel out of the eyes in layer mode, and a backend that cannot make the layer falls back to drawing it into the eyes. On the Quest, debug.wiicompiled.panel_layer 0 selects the old path at run time. Measured there at a race start (render_scale 0.8), the layer costs nothing while the panel is closed; while it is open, app GPU time is 10.5 ms against 9.7 ms drawn into the eyes, with unchanged frame rates. The replay tests cover lazy creation, cancelled frames, closed and unplaced panels, and render-first pacing on D3D12 and Windows Vulkan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
116 lines
5.2 KiB
C++
116 lines
5.2 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#if defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
|
|
|
#include "vr/openxr_backend.h"
|
|
#include "vr/openxr_runtime.h"
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace mkw::vr {
|
|
|
|
// The frame vocabulary is shared with the Vulkan backend (vr/openxr_backend.h).
|
|
// These aliases keep the D3D12 spelling that the replay tests and the original
|
|
// integration code were written against.
|
|
using OpenXRD3D12FrameMode = OpenXRFrameMode;
|
|
using OpenXRD3D12BeginStatus = OpenXRBeginStatus;
|
|
using OpenXRD3D12SubmissionStatus = OpenXRSubmissionStatus;
|
|
using OpenXRD3D12Presentation = OpenXRPresentation;
|
|
using OpenXRD3D12Frame = OpenXRBackendFrame;
|
|
|
|
struct OpenXRD3D12GraphicsRequirements {
|
|
uint32_t adapter_luid_low = 0;
|
|
int32_t adapter_luid_high = 0;
|
|
uint32_t minimum_feature_level = 0;
|
|
};
|
|
|
|
// Same-device Dawn/OpenXR D3D12 backend.
|
|
//
|
|
// Startup is deliberately split in two. QueryGraphicsRequirements() runs
|
|
// after OpenXRRuntime::Initialize() but before aurora_initialize(), allowing
|
|
// its LUID to be placed in AuroraConfig. BindAurora() runs afterwards and
|
|
// rejects any device/queue that does not match the queried runtime adapter.
|
|
//
|
|
// All methods from BeginFrame() through FinishFrame(), plus PollEvents on the
|
|
// associated OpenXRRuntime, belong to one XR pacing thread. Aurora's frame
|
|
// worker never calls OpenXR: its post-submit callback only publishes a token
|
|
// that WaitForSubmission() consumes. This is the synchronization boundary
|
|
// required by the asynchronous sealed-frame renderer.
|
|
class OpenXRD3D12Backend final {
|
|
public:
|
|
explicit OpenXRD3D12Backend(OpenXRLogCallback logger = {});
|
|
~OpenXRD3D12Backend();
|
|
|
|
OpenXRD3D12Backend(const OpenXRD3D12Backend&) = delete;
|
|
OpenXRD3D12Backend& operator=(const OpenXRD3D12Backend&) = delete;
|
|
OpenXRD3D12Backend(OpenXRD3D12Backend&&) = delete;
|
|
OpenXRD3D12Backend& operator=(OpenXRD3D12Backend&&) = delete;
|
|
|
|
bool QueryGraphicsRequirements(OpenXRRuntime& runtime);
|
|
bool BindAurora(OpenXRRuntime& runtime);
|
|
|
|
OpenXRD3D12BeginStatus BeginFrame(const OpenXRD3D12Presentation& presentation,
|
|
OpenXRD3D12Frame& frame);
|
|
|
|
// timeout_ms == UINT32_MAX waits until Aurora publishes this token or
|
|
// Shutdown() interrupts the wait. A timeout does not release XR images;
|
|
// the caller may keep pacing with RepeatFrame while Aurora still owns them.
|
|
OpenXRD3D12SubmissionStatus WaitForSubmission(const OpenXRD3D12Frame& frame,
|
|
uint32_t timeout_ms = UINT32_MAX);
|
|
|
|
// Withdraws this token only if Aurora has not encoded it. On success no GPU
|
|
// command can reference the acquired images, and FinishFrame(frame, false)
|
|
// is required to release them and close the compositor frame.
|
|
bool TryCancelPendingFrame(OpenXRD3D12Frame& frame);
|
|
|
|
// Ends the current compositor cycle with the last completed layer and starts
|
|
// another, without releasing or changing Aurora's pending images/render token.
|
|
// The original render poses remain attached to the pending and retained images.
|
|
bool RepeatFrame(const OpenXRD3D12Frame& frame);
|
|
|
|
// Releases acquired images and calls xrEndFrame. submit_layer must only be
|
|
// true after WaitForSubmission returned Success. Immersive frames submit
|
|
// XrCompositionLayerProjection; virtual-screen frames submit an
|
|
// XrCompositionLayerQuad using the single mono target, placed as the
|
|
// presentation's quad_anchored/quad_pose describe. If no new usable layer is
|
|
// available, resubmits the retained layer using the current display time.
|
|
bool FinishFrame(OpenXRD3D12Frame& frame, bool submit_layer);
|
|
|
|
// Render-first path when interpolation is off. Aurora renders into acquired
|
|
// non-retained XR images while no compositor frame is open. BeginFrameForPacket
|
|
// accepts only a completed packet; CopyRenderedEyes verifies the already queued
|
|
// bridge copy. FinishFrame releases the images and submits their original poses.
|
|
OpenXRBeginStatus PreparePacket(const OpenXRPresentation& presentation, OpenXRBackendFrame& packet);
|
|
bool TryCancelPendingPacket(OpenXRBackendFrame& packet);
|
|
OpenXRBeginStatus BeginFrameForPacket(const OpenXRBackendFrame& packet, OpenXRBackendFrame& frame);
|
|
OpenXRSubmissionStatus CopyRenderedEyes(const OpenXRBackendFrame& frame);
|
|
OpenXRBeginStatus KeepAliveCycle();
|
|
|
|
// Call on the XR owner thread after Aurora's worker is idle and before
|
|
// aurora_shutdown(). Safe to repeat. False means a submitted D3D12 command
|
|
// could not be fenced; the caller must retain this backend and its runtime
|
|
// for the process lifetime instead of destroying possibly live resources.
|
|
bool Shutdown();
|
|
|
|
bool IsBound() const;
|
|
// False once the settings panel's own layer could not be set up; the panel
|
|
// is then drawn into the eyes again.
|
|
bool PanelLayerAvailable() const;
|
|
const OpenXRD3D12GraphicsRequirements& GraphicsRequirements() const;
|
|
int64_t SwapchainFormat() const;
|
|
const std::string& LastError() const;
|
|
|
|
private:
|
|
class Impl;
|
|
std::unique_ptr<Impl> m_impl;
|
|
};
|
|
|
|
} // namespace mkw::vr
|
|
|
|
#endif // defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|