mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 10:00:27 +02:00
Show the headset settings panel as its own OpenXR quad layer
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>
This commit is contained in:
1 parent
dd7f046214
commit
54c07c982b
22 files changed
+1223
-420
No files matched your search
@@ -5,6 +5,7 @@
|
||||
#if defined(MKW_ENABLE_OPENXR)
|
||||
|
||||
#include "vr/openxr_runtime.h"
|
||||
#include "vr/openxr_settings_panel.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@@ -42,6 +43,44 @@ enum class OpenXRSubmissionStatus {
|
||||
ShuttingDown,
|
||||
};
|
||||
|
||||
// The headset settings panel as a compositor quad layer of its own, over the
|
||||
// eyes or the menu screen, so the eye resolution never limits its text. Its
|
||||
// image is rendered with the frame's eyes (Aurora's panel stereo target) into a
|
||||
// swapchain of the panel canvas's own size. Nothing is allocated or copied
|
||||
// until the panel first opens, and nothing is submitted while it is closed.
|
||||
struct OpenXRPanelLayer {
|
||||
// The frame renders the panel's image: set by the pacing thread when the
|
||||
// panel is open, cleared by a backend that could not provide the layer.
|
||||
bool requested = false;
|
||||
// Where it hangs in the application space, once the head pose is known.
|
||||
bool placed = false;
|
||||
XrPosef pose{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}};
|
||||
float width_meters = 0.0f;
|
||||
float height_meters = 0.0f;
|
||||
};
|
||||
|
||||
// The panel image's size, which is the settings panel canvas's.
|
||||
inline constexpr uint32_t kOpenXRPanelLayerWidth = static_cast<uint32_t>(kSettingsPanelWidthPixels);
|
||||
inline constexpr uint32_t kOpenXRPanelLayerHeight = static_cast<uint32_t>(kSettingsPanelHeightPixels);
|
||||
|
||||
// The panel's layer, submitted after (so over) the scene's.
|
||||
inline XrCompositionLayerQuad OpenXRPanelQuadLayer(const OpenXRPanelLayer& panel, XrSpace space,
|
||||
XrSwapchain swapchain) noexcept {
|
||||
XrCompositionLayerQuad quad{XR_TYPE_COMPOSITION_LAYER_QUAD};
|
||||
// ImGui leaves premultiplied colour in the cleared panel image.
|
||||
quad.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
quad.space = space;
|
||||
quad.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
|
||||
quad.subImage.swapchain = swapchain;
|
||||
quad.subImage.imageRect = {{0, 0},
|
||||
{static_cast<int32_t>(kOpenXRPanelLayerWidth),
|
||||
static_cast<int32_t>(kOpenXRPanelLayerHeight)}};
|
||||
quad.subImage.imageArrayIndex = 0;
|
||||
quad.pose = panel.pose;
|
||||
quad.size = {panel.width_meters, panel.height_meters};
|
||||
return quad;
|
||||
}
|
||||
|
||||
struct OpenXRPresentation {
|
||||
OpenXRFrameMode mode = OpenXRFrameMode::ImmersiveProjection;
|
||||
|
||||
@@ -56,6 +95,8 @@ struct OpenXRPresentation {
|
||||
// head pose good enough to anchor against.
|
||||
bool quad_anchored = false;
|
||||
XrPosef quad_pose{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}};
|
||||
|
||||
OpenXRPanelLayer panel;
|
||||
};
|
||||
|
||||
struct OpenXRBackendFrame {
|
||||
|
||||
@@ -98,6 +98,9 @@ public:
|
||||
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;
|
||||
|
||||
@@ -78,6 +78,9 @@ public:
|
||||
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 OpenXRVulkanGraphicsRequirements& GraphicsRequirements() const;
|
||||
int64_t SwapchainFormat() const;
|
||||
const std::string& LastError() const;
|
||||
|
||||
@@ -95,6 +95,9 @@ public:
|
||||
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 OpenXRWindowsVulkanGraphicsRequirements& GraphicsRequirements() const;
|
||||
int64_t SwapchainFormat() const;
|
||||
const std::string& LastError() const;
|
||||
|
||||
@@ -54,6 +54,9 @@ public:
|
||||
bool Shutdown() {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->Shutdown(); }, backend_);
|
||||
}
|
||||
bool PanelLayerAvailable() {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->PanelLayerAvailable(); }, backend_);
|
||||
}
|
||||
int64_t SwapchainFormat() {
|
||||
return std::visit([&](auto& backend) -> int64_t { return backend->SwapchainFormat(); }, backend_);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user