Added foveated rendering for the Quest

- Eyes render under a VK_EXT_fragment_density_map: full rate around each eye's forward direction,
  2x2 then 4x4 pixel blocks towards the edges ([vr] foveation = off|low|medium|high, default off).
  XR_FB_foveation cannot help here: the runtime's maps only shape passes drawing into its
  swapchain, and the eyes reach it through a copy.
- aurora-main/patches/dawn/aurora_fdm.inc: Dawn enables the extension only on request and for
  dynamic rendering, flags every render pipeline, and chains an immutable RG8 map into any pass
  whose first color attachment is a view bound to one (ABI: include/aurora/dawn_fdm_abi.h).
- android/Build-QuestDawn.ps1 builds the pinned Dawn revision with those patches for arm64
  (dawn-build CI flags, protobuf off) into a cached package; Build-Quest.ps1 links it
  (-StockDawn opts out) and AuroraDawnProvider.cmake enables the ABI from its manifest.
- lib/gfx/foveation.hpp generates the maps (32 px per texel, densities 255/127/63); an eye is
  foveated only when single_pass_eyes draws it in one render pass. Menus never are.
- Live level from the headset panel's VR tab and the launcher; the launch decides whether the
  device has maps. debug.wiicompiled.foveation and debug.wiicompiled.fdm for A/B.
- Tests: Foveation cases in gx_fifo_tests, mkw_vr_config_tests. Docs: OPENXR.md, quest-port.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
iChris4andClaude Opus 5.5 committed 2026-09-24 19:03:17 +02:00
1 parent ceeeba0332
commit cc653272c8
30 files changed
+1527 -14

No files matched your search

+5
View File
@@ -245,6 +245,11 @@ typedef struct {
// Enables renderer features needed by an external XR compositor. The normal
// desktop path is unchanged when false.
bool xrInterop;
// Asks for fragment density maps on the Vulkan device, for foveated eye
// rendering (aurora_set_stereo_foveation). Only a Dawn built with Aurora's
// patches has them (the Quest build). Every render pipeline is then built to
// run under a density map, so set it only when foveation may be used.
bool xrFragmentDensityMap;
// Optional OpenXR-selected D3D adapter. Supplying the runtime's LUID before
// device creation keeps Dawn and the compositor on the same physical GPU.
bool hasD3D12AdapterLuid;
+51
View File
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <stdint.h>
// Versioned C ABI for the fragment density maps the patched Dawn attaches to Aurora's immersive
// eye render passes (VK_EXT_fragment_density_map through dynamic rendering, see
// patches/dawn/aurora_fdm.inc). The Quest build links that Dawn statically and
// AuroraDawnProvider.cmake defines AURORA_DAWN_FDM_ABI when the package carries it. Devices and
// texture views are WGPUDevice and WGPUTextureView handles.
#define AURORA_DAWN_FDM_ABI 1
#if defined(AURORA_DAWN_FDM_IMPLEMENTATION)
#define AURORA_DAWN_FDM_API DAWN_NATIVE_EXPORT
#else
#define AURORA_DAWN_FDM_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// VK_EXT_fragment_density_map is enabled on the device, for non-subsampled attachments.
uint32_t enabled;
// The framebuffer area one density map texel may cover.
uint32_t minTexelWidth;
uint32_t minTexelHeight;
uint32_t maxTexelWidth;
uint32_t maxTexelHeight;
} AuroraDawnFdmCaps;
AURORA_DAWN_FDM_API uint32_t AuroraDawnFdmVersion(void);
// Asks the next Vulkan device Dawn creates for fragment density maps. They are only enabled when
// that device renders through dynamic rendering and supports non-subsampled attachments. Call it
// before requesting the device.
AURORA_DAWN_FDM_API void AuroraDawnFdmRequest(int enable);
// Returns caps->enabled.
AURORA_DAWN_FDM_API int AuroraDawnFdmQuery(void* device, AuroraDawnFdmCaps* caps);
// Uploads an immutable RG8 density map, `width` by `height` texels in packed rows, and returns its
// id, or 0 on failure. A map becomes usable once its upload has completed on the GPU: the driver
// reads a non-dynamic map on the CPU when a render pass using it is recorded.
AURORA_DAWN_FDM_API uint64_t AuroraDawnFdmCreateMap(void* device, uint32_t width, uint32_t height,
const uint8_t* rg8);
AURORA_DAWN_FDM_API int AuroraDawnFdmMapReady(void* device, uint64_t map);
// Frees the map once the GPU is done with it, and unbinds it from any view.
AURORA_DAWN_FDM_API void AuroraDawnFdmReleaseMap(void* device, uint64_t map);
// Every render pass whose first color attachment is `view` gets `map` as its fragment density map
// while the map is ready; 0 unbinds. The binding keeps the view alive until it is unbound. Returns 0
// when the map is unknown or too small to cover the view.
AURORA_DAWN_FDM_API int AuroraDawnFdmBind(void* device, void* view, uint64_t map);
#ifdef __cplusplus
}
#endif
+12
View File
@@ -107,6 +107,18 @@ bool aurora_get_stereo_skip_copy_clears();
void aurora_set_stereo_single_pass_eyes(bool enabled);
bool aurora_get_stereo_single_pass_eyes();
// Fixed foveated rendering of the immersive eyes: 0 off, 1 low, 2 medium, 3
// high. Each eye's render pass runs under a fragment density map that shades
// the periphery in 2x2, then 4x4 pixel blocks, the higher the level the closer
// to the centre. Only an eye drawn in a single render pass (single_pass_eyes)
// is foveated; menus on the virtual screen never are. Live, but it needs a
// device created with AuroraConfig::xrFragmentDensityMap and a Dawn built with
// Aurora's patches (the Quest build); aurora_stereo_foveation_available says
// whether this session has both.
void aurora_set_stereo_foveation(uint32_t level);
uint32_t aurora_get_stereo_foveation();
bool aurora_stereo_foveation_available();
// Places orthographic GX draws (menus, HUD, 2D overlays) on a fixed virtual
// screen during immersive replay instead of stretching them across the whole
// eye viewport. The screen hangs `distance` world units straight ahead of the