Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/specs/extensions/XR_DXR_weave.md
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,16 @@ desktop-Linux runtime it keeps a mismatched overlay off the wire itself.
With v14, a frame whose overlay was ignored also resets "unchanged": the first overlay the display
processor is offered after one is passed as changed, whatever the caller declared, since the
display processor's cached layer predates the ignored frames.
**Android: the overlay is per submit, and an unreadable one refuses (v18).** The Android engine
caches an overlay import by buffer identity (the caller re-sends the same `AHardwareBuffer` every
frame), and before v18 that cache was also a *standing* overlay: once imported, it was
composited on every later submit, including one that chained no overlay. From v17 an overlay is
composited only on a submit that chains one (the cache is kept, so re-sending the same buffer
costs no re-import), and a chained overlay that cannot be imported refuses the submit with
`XR_ERROR_RUNTIME_FAILURE` before the woven output is touched — the v16 rule above. A caller
whose overlay is its whole 2D (browser-pvt#226 on Android) switches the overlay off while its page
scrolls, so on a pre-v18 Android runtime it would see its last page composited over a page that
had moved; such a caller gates on `extensionVersion >= 18`.

**The import cache.** An fd is not an identity: every hand-off is a new number. The service
keys its input import cache on `bufferId` when non-zero and on the fd's `(st_dev, st_ino)`
Expand Down Expand Up @@ -964,6 +974,9 @@ any unknown chained struct. One `weave(v13)` WARN in the service log per edge.
**v17 is a gate for the same caller as v16**: one whose overlay IS its 2D must not rely on a
mismatched overlay being dropped by an older desktop-Linux runtime, which composites it stretched;
it keeps such an overlay off the wire there instead.
| 18 | No new structure: on Android an overlay is **per submit** (composited only on a submit that chains one; before v18 the last imported overlay was composited on every later submit) and a chained overlay the engine cannot import **refuses the submit before the woven output is touched** — the v16 rule. An Android caller that hands its whole 2D over as the overlay gates on `extensionVersion >= 18`. The macOS engine still drops an unreadable overlay. |

**v18 is the same gate on Android**, for the same kind of caller.

**v16 is a gate for one kind of caller**: one whose overlay IS its 2D (a whole-page overlay)
must not send it to an older desktop-Linux runtime, which would weave without it and return
Expand Down
11 changes: 10 additions & 1 deletion src/external/openxr_includes/openxr/XR_DXR_weave.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@
* overlay IS its 2D gates on extensionVersion >= 17 before relying on it, and
* otherwise keeps a mismatched overlay off the wire itself.
*
* Android: an overlay is per submit, and an unreadable one refuses (SPEC_VERSION
* 18). No new structure: from v18 the Android engine applies the v16 rule too
* (a chained overlay it cannot import refuses the submit, XR_ERROR_RUNTIME_FAILURE,
* before the woven output is touched) and composites an overlay only on a submit
* that chains one. Before v18 it composited the last overlay it had imported on
* every later submit, chained or not. An Android caller that hands the whole of
* its 2D over as the overlay gates on extensionVersion >= 18. The macOS engine
* still drops an unreadable overlay.
*
* Overlay filter strength (SPEC_VERSION 15). XrWeaveSubmitOverlayFilterDXR, chained
* next to an XrWeaveSubmitOverlaysDXR: how strongly a display processor that
* band-limits the 2D layer for its lens filters it, 0..1 (0 = no lens filtering,
Expand Down Expand Up @@ -303,7 +312,7 @@ extern "C" {
#endif

#define XR_DXR_weave 1
#define XR_DXR_weave_SPEC_VERSION 17
#define XR_DXR_weave_SPEC_VERSION 18
#define XR_DXR_WEAVE_EXTENSION_NAME "XR_DXR_weave"

// Reserved 1004999190..199. Final values reconcile with the Khronos registry
Expand Down
9 changes: 9 additions & 0 deletions src/xrt/compositor/multi/comp_multi_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,15 @@ struct multi_compositor
bool overlay_first_use;
struct vk_local2d_composite overlay_blend;
bool overlay_blend_initialized;
/*!
* XR_DXR_weave v18: THIS submit chained an overlay. The import above is
* a cache (an AHardwareBuffer is re-sent every frame and matched by
* pointer), so @c overlay_image outlives the submit that brought it; the
* overlay is composited only when the current submit carries one.
*/
bool overlay_this_submit;
//! Submits refused because their chained overlay could not be imported.
uint32_t overlay_refusals;
//! @}

//! @name Arch-C weave satellite (#1277 P0) — service-presented weave
Expand Down
28 changes: 27 additions & 1 deletion src/xrt/compositor/multi/comp_multi_weave_android.c
Original file line number Diff line number Diff line change
Expand Up @@ -1828,6 +1828,24 @@ comp_multi_weave_submit(struct xrt_compositor *xc,
}

// v4 overlay: same, into the SEPARATE overlay cache.
//
// XR_DXR_weave v18 (browser-pvt#226), two rules the desktop-Linux engine
// has had since v16 and the D3D11 service always had:
// 1. PER SUBMIT. The cache is keyed by buffer identity because the
// caller re-sends the same AHardwareBuffer every frame, but a cached
// import is NOT a standing overlay: a submit that chains none is woven
// with none. Before v18 the last imported overlay was composited on
// every later submit, so a caller that stops sending one (the
// browser's whole-page overlay switches itself off while the page
// scrolls) got its last page composited over a page that had moved.
// 2. REFUSE, don't drop. A chained overlay that cannot be imported
// refuses the submit HERE, before anything is recorded, so the woven
// output is left exactly as the previous accepted submit left it. A
// caller that hands its whole 2D over as the overlay reads "accepted
// with the overlay chained" as "composited" and presents the woven
// output as the frame; before v18 that frame would have had its 2D
// missing.
mc->weave.overlay_this_submit = overlay != XRT_GRAPHICS_BUFFER_HANDLE_INVALID;
if (overlay != XRT_GRAPHICS_BUFFER_HANDLE_INVALID &&
(mc->weave.overlay_image == VK_NULL_HANDLE || mc->weave.overlay_ahb != (void *)overlay)) {
weave_release_overlay(vk, mc);
Expand All @@ -1840,6 +1858,14 @@ comp_multi_weave_submit(struct xrt_compositor *xc,
overlay = XRT_GRAPHICS_BUFFER_HANDLE_INVALID;
U_LOG_W("weave(#1036) v4: overlay import cached (%ux%u)", mc->weave.overlay_w,
mc->weave.overlay_h);
} else {
const uint32_t n = mc->weave.overlay_refusals++;
if (n == 0 || (n % 300) == 0) {
U_LOG_W("weave(#1036) v18: overlay import failed — submit REFUSED, woven output "
"untouched (refusals=%u)",
n + 1);
}
break;
}
}

Expand Down Expand Up @@ -2380,7 +2406,7 @@ comp_multi_weave_submit(struct xrt_compositor *xc,
// blend, so crisp 2D lands on top of the interlaced 3D at screen depth.
// The overlay is NOT woven — it is drawn after process_atlas onto the same
// output attachment.
if (mc->weave.overlay_image != VK_NULL_HANDLE) {
if (mc->weave.overlay_image != VK_NULL_HANDLE && mc->weave.overlay_this_submit) {
bool blend_ready = mc->weave.overlay_blend_initialized;
if (!blend_ready) {
blend_ready = vk_local2d_composite_init(&mc->weave.overlay_blend, vk, WEAVE_VK_FORMAT,
Expand Down
Loading