XR_EXT_spatial_container_self_rendering

מחרוזת שם

XR_EXT_spatial_container_self_rendering

סוג התוסף

תוסף למכונה

מספר השלוחה הרשום

814

גרסה

1

סטטוס האישור

לא אושר

תלויות של תוספים וגרסאות

XR_EXT_spatial_container

תאריך השינוי האחרון

2026-08-06

סטטוס IP

אין תלונות ידועות על הפרת קניין רוחני.

שותפים ביצירת התוכן

Lachlan Ford, Google
Andreas Loeve Selvik, Meta Platforms
Adam Gousetis, Meta Platforms
Bjorn Swenson, LÖVR
Cass Everitt, Meta Platforms
Christian Kruse, Meta Platforms
Denny Rönngren, Varjo Technologies
Fredia Huya-Kouadio, Godot Engine
Jakob Bornecrantz, NVIDIA
Jared Finder, Google
Jonathan Wright, Meta Platforms
Jian Zhang, ByteDance
Kurtis Eveleigh, Qualcomm
Mauricio Narvaez, Meta Platforms
Nick Klingensmith, Qualcomm
Nikita Lutsenko, Meta Platforms
Praveen Babu J D, ByteDance
Rylie Pavlik, Collabora
Salar Khan, Google
Shuai Liu, ByteDance
Walter Luh, Meta Platforms
Yin Li, Microsoft

סקירה כללית

התוסף הזה מגדיר "עיבוד עצמי" למאגרים מרחביים. כל הפיקסלים של קונטיינר מרחבי שמעובד באופן עצמאי נוצרים על ידי אפליקציה ונשלחים לסביבת זמן הריצה באמצעות שרשראות החלפה (swapchains) ושכבות קומפוזיציה רגילות של OpenXR. מכיוון שקונטיינרים מרחביים לא תמיד תופסים את כל הפיקסלים של המסך, סביבת זמן הריצה מודיעה לאפליקציות על הרזולוציה המומלצת ועל הגדרת התצוגה של כל קונטיינר מרחבי, כדי לאפשר לאפליקציות לעבד בצורה יעילה יותר.

התוסף הזה, בשילוב עם XR_EXT_spatial_container, נועד להציע קבוצת-על של היכולות של רינדור שכבת קומפוזיציה רגילה של OpenXR 1.x. בסביבות זמן ריצה של OpenXR 1.x שתומכות ברינדור גרפי ובתוסף הזה, חובה להגדיר את XrSystemSpatialContainerPropertiesEXT :: supportsImmersive כ-true כדי לציין שהן תומכות בקונטיינרים מרחביים סוחפים.

מחזור החיים של רינדור קונטיינר מרחבי

כדי להשתמש ברינדור עצמי של קונטיינר מרחבי, האפליקציה מגדירה את XrSpatialContainerCreateInfoEXT :: graphicsPresentation ל-XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT כשמפעילים את xrCreateSpatialContainerEXT . לאחר מכן, האפליקציה הזו יכולה לנהל את העיבוד של מאגר מרחבי על ידי קריאה לפונקציות xrBeginSpatialContainerRenderingEXT ו-xrEndSpatialContainerRenderingEXT. הפונקציות האלה מחליפות את xrBeginSession ואת xrEndSession . הן לא פעולות לכל פריים, כמו xrBeginFrame ו-xrEndFrame .

בכל פריים, האפליקציה מבצעת את השלבים הבאים:

  • מפעילים את xrWaitFrame ואת xrBeginFrame . לפונקציות האלה אין מבנים ספציפיים למאגר, והן פועלות כמו במפרט הליבה.
  • אחזור של תנוחות תצוגה, פרמטרים של הקרנה והמלצות לעיבוד (rendering) לכל מאגרי הנתונים המרחביים שמעובדים באופן פעיל באמצעות xrLocateSpatialContainerViewsEXT . לכל מאגר מרחבי, זמן הריצה מדווח אם צריך לעבד את שכבות הקומפוזיציה שלו ואת הדרך המומלצת לעבד את השכבות על ידי מילוי XrSpatialContainerViewStateEXT .
  • עיבוד פיקסלים לשכבות קומפוזיציה כרגיל. לפעולות האלה אין מבנים ספציפיים למאגר.
  • שולחים שכבות קומפוזיציה לכל הקונטיינרים המרחביים שמעובדים באופן פעיל על ידי קריאה ל-xrEndFrame ושרשור של XrSpatialContainerLayerFrameEndInfoEXT .

השמדה של נקודת אחיזה (handle) של XrSpatialContainerEXT מסירה אותה באופן משתמע מקבוצת הרינדור הפעילה. אפליקציה עשויה להרוס מאגר מרחבי גם אם היא ביצעה קריאה מוצלחת ל-xrBeginSpatialContainerRenderingEXT שלא משויכת לקריאה תואמת ל-xrEndSpatialContainerRenderingEXT . זמן הריצה חייב להתנהג כאילו מתבצעת קריאה משתמעת ל-xrEndSpatialContainerRenderingEXT, אם יש צורך בכך בשלב מוקדם בהטמעה של xrDestroySpatialContainerEXT, אם היא מוחזרת בהצלחה.

כשאפליקציה מקבלת אירוע XrEventDataSpatialContainerClosedEXT בשביל מאגר בקבוצת הרינדור הפעילה, האפליקציה צריכה להפעיל את xrEndSpatialContainerRenderingEXT ולהשמיד את נקודת האחיזה XrSpatialContainerEXT.

הפונקציה xrBeginSpatialContainerRenderingEXT מוסיפה את מאגר הנתונים המרחבי לקבוצת הרינדור הפעילה לכל סשן, וכך מאפשרת לאפליקציה לשלוח שכבות קומפוזיציה של מאגר הנתונים המרחבי אל xrEndFrame .

XrResult xrBeginSpatialContainerRenderingEXT(
    XrSession                                   session,
    const XrSpatialContainerBeginInfoEXT*       beginInfo);

תיאורי פרמטרים

בדרך כלל, אפליקציות קוראות לפונקציה הזו בתגובה לאירוע visible-changed, כשהערך של XrEventDataSpatialContainerVisibleChangedEXT :: visible מוגדר כ-true.

אם המאגר המרחבי לא נוצר עם XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT כשקוראים ל-xrCreateSpatialContainerEXT , זמן הריצה חייב להחזיר את XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT .

אם הקונטיינר המרחבי כבר נמצא בקבוצת הרינדור הפעילה, זמן הריצה חייב להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT .

אם הפונקציה xrBeginSpatialContainerRenderingEXT נקראת בזמן שבו האפליקציה לא יכולה לקרוא ל-xrWaitFrame (כלומר בתוך החלון xrBeginFrame ו-xrEndFrame), זמן הריצה חייב להחזיר את XR_ERROR_CALL_ORDER_INVALID .

שימוש תקין (משתמע)

Thread Safety

קודי החזרה

הצלחה

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

נכשל

  • XR_ERROR_CALL_ORDER_INVALID
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT
  • XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT
  • XR_ERROR_VALIDATION_FAILURE
  • XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED

המבנה XrSpatialContainerBeginInfoEXT משמש לציון הפרמטרים לתחילת העיבוד של קונטיינר מרחבי.

typedef struct XrSpatialContainerBeginInfoEXT {
    XrStructureType            type;
    const void*                next;
    XrSpatialContainerEXT      spatialContainer;
    XrViewConfigurationType    primaryViewConfigurationType;
} XrSpatialContainerBeginInfoEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫spatialContainer הוא ה-XrSpatialContainerEXT שבו מתחיל העיבוד.
  • ‫primaryViewConfigurationType הוא הערך הראשי של XrViewConfigurationType שמשמש למאגר המרחבי.

‫primaryViewConfigurationType היא הגדרת התצוגה שהאפליקציה מתכוונת להשתמש בה במהלך העיבוד. למטרות אופטימיזציה, זמן הריצה עשוי להפחית את הגדרת התצוגה לסוג עם פחות תצוגות (למשל, קונטיינר רחוק מאוד וקטן, כך שלא ניתן להבחין בסטריאו). זמן הריצה מחזיר פרטים על הגדרת התצוגה שהתיישנה מקריאות ל-xrLocateSpatialContainerViewsEXT .

שימוש תקין (משתמע)

הפונקציה xrEndSpatialContainerRenderingEXT מסירה את מאגר הנתונים המרחבי מקבוצת העיבוד הפעילה.

XrResult xrEndSpatialContainerRenderingEXT(
    XrSession                                   session,
    const XrSpatialContainerEndInfoEXT*         endInfo);

תיאורי פרמטרים

בדרך כלל, אפליקציות קוראות לפונקציה הזו בתגובה לאירוע visible-changed, כשהערך של XrEventDataSpatialContainerVisibleChangedEXT :: visible מוגדר כ-false.

אם הקונטיינר המרחבי לא נמצא בקבוצת הרינדור הפעילה, זמן הריצה חייב להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT .

אם הפונקציה xrEndSpatialContainerRenderingEXT נקראת בזמן שבו האפליקציה לא יכולה לקרוא לפונקציה xrWaitFrame (כלומר, בתקופה שבין הקריאות לפונקציות xrBeginFrame ו-xrEndFrame), זמן הריצה חייב להחזיר את הערך XR_ERROR_CALL_ORDER_INVALID .

שימוש תקין (משתמע)

Thread Safety

קודי החזרה

הצלחה

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

נכשל

  • XR_ERROR_CALL_ORDER_INVALID
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT
  • XR_ERROR_VALIDATION_FAILURE

המבנה XrSpatialContainerEndInfoEXT משמש לציון הפרמטרים לסיום העיבוד של קונטיינר מרחבי.

typedef struct XrSpatialContainerEndInfoEXT {
    XrStructureType          type;
    const void*              next;
    XrSpatialContainerEXT    spatialContainer;
} XrSpatialContainerEndInfoEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫spatialContainer הוא ה-XrSpatialContainerEXT שבו העיבוד מסתיים.

שימוש תקין (משתמע)

איתור תצוגות באמצעות xrLocateSpatialContainerViewsEXT

הפונקציה xrLocateSpatialContainerViewsEXT מאתרת תצוגות של קבוצת מאגרים מרחביים.

XrResult xrLocateSpatialContainerViewsEXT(
    XrSession                                   session,
    const XrSpatialContainerViewsLocateInfoEXT* locateInfo,
    uint32_t                                    viewStateCount,
    XrSpatialContainerViewStateEXT*             viewStates,
    uint32_t                                    viewCount,
    XrView*                                     views);

תיאורי פרמטרים

  • ‫session הוא ה-XrSession .
  • ‫locateInfo הוא מצביע למבנה XrSpatialContainerViewsLocateInfoEXT.
  • ‫viewStateCount הוא מספר הפריטים במערך viewStates.
  • ‫viewStates הוא מצביע למערך של מבני XrSpatialContainerViewStateEXT שמאוכלסים על ידי סביבת זמן הריצה.
  • ‫viewCount הוא מספר הפריטים במערך views.
  • ‫views הוא מצביע למערך של מבני XrView.

הפונקציה הזו מחליפה את xrLocateViews , ומאפשרת לאפליקציה לשלוח שאילתות לגבי תצוגות של כמה קונטיינרים מרחביים בו-זמנית.

התצוגות של כל המכלים המרחביים מוחזרות במערך views היחיד. התצוגות מסודרות לפי האינדקס של הקונטיינר המרחבי במערך XrSpatialContainerViewsLocateInfoEXT :: viewLocateInfos, ואז לפי אינדקס התצוגה של הקונטיינר הזה.

לדוגמה, אם אפליקציה מספקת שלושה מאגרי נתונים מרחביים ב-XrSpatialContainerViewsLocateInfoEXT :: viewLocateInfos :

  • אינדקס 0: XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO (צפייה אחת)
  • אינדקס 1: XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO (2 צפיות)
  • אינדקס 2: XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET (4 צפיות)

לאחר מכן, סביבת זמן הריצה חייבת למלא את המערך views ב-7 תצוגות:

  • ‫views [0] היא התצוגה של מאגר 0.
  • ‫views [1] הוא התצוגה של העין השמאלית במאגר 1.
  • ‫views [2] הוא התצוגה של העין הימנית במאגר 1.
  • ‫views [3] הוא התצוגה של העין השמאלית במאגר 2.
  • ‫views [4] הוא התצוגה של העין הימנית במאגר 2.
  • ‫views [5] הוא התצוגה הפנימית של העין השמאלית במאגר 2.
  • ‫views [6] היא תצוגת האינסרט של העין הימנית של מאגר 2.

אם viewCount לא שווה לסכום של מספרי הצפיות של כל סוג של הגדרת תצוגה מבוקשת של מאגר מרחבי, זמן הריצה חייב להחזיר XR_ERROR_VALIDATION_FAILURE .

למטרות אופטימיזציה, זמן הריצה עשוי להפחית את תצורת התצוגה לסוג עם פחות תצוגות (למשל, קונטיינר רחוק מאוד וקטן, כך שאי אפשר להבחין בסטריאו). אם סביבת זמן הריצה מפחיתה את הגדרת התצוגה, סביבת זמן הריצה עדיין חייבת להחזיר את מספר התצוגות המקורי של מאגר התגים הזה, ולאכלס את התצוגות הנוספות בעותקים משוכפלים של התצוגות שהופחתו. לדוגמה, אם XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO מופחת ל-XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO , גם אינדקס 0 וגם אינדקס 1 יכילו את התצוגה המונופונית היחידה. לכן, מספר הצפיות הכולל שמוחזר במערך views לא תלוי בהחלטה של זמן הריצה אם להפחית את הערך של הגדרות תצוגה כלשהן או לא.

סביבת זמן הריצה צריכה להתאים כל XrView :: fov שמוחזר, כך שהפירמידה הקטומה תהיה קטנה ככל האפשר ועדיין תכיל את כל הגבולות של המאגר המרחבי התואם. זמני ריצה עשויים להחזיר שדות ראייה לא סימטריים, למשל אם קונטיינר מרחבי נמצא בזווית אלכסונית לתצוגה של המשתמש, או אם הוא מוסתר חלקית על ידי אובייקט אחר. סביבות זמן ריצה יכולות למקם באופן חופשי את משטח הרינדור של מאגר המידע המרחבי. בגלל האופי של רינדור בכמה אפליקציות, שבו קונטיינרים מרחביים מנותקים מהמשתמש, יכול להיות שזמן הריצה יחזיר ערכי XrView שלא מתאימים לרינדור פיקסלים. לדוגמה, אם הקונטיינר המרחבי לא גלוי במסך, אין ערכים חוקיים שאפשר להגדיר בהם את XrView :: fov. במקרים כאלה, סביבות זמן הריצה חייבות להגדיר את XrSpatialContainerViewStateEXT :: shouldSubmitLayers כ-false.

זמן הריצה מחזיר מידע נוסף על מצב העיבוד של כל מאגר מרחבי במערך viewStates. אם viewStateCount לא שווה ל-XrSpatialContainerViewsLocateInfoEXT :: viewLocateInfoCount , זמן הריצה חייב להחזיר את XR_ERROR_VALIDATION_FAILURE .

אחרי שסביבת זמן הריצה מוסיפה לתור אירוע XrEventDataSpatialContainerClosedEXT של מאגר מרחבי, הפונקציה הזו חייבת להחזיר את הערך XR_FALSE ב-XrSpatialContainerViewStateEXT :: shouldSubmitLayers ואת הערך 0 ב-XrSpatialContainerViewStateEXT :: viewStateFlags של המאגר המרחבי התואם.

במכלים מרחביים עם מיקומים שמשתנים באופן פעיל בעולם האמיתי, זמן הריצה צריך להביא בחשבון את התנועה של המכל כשממלאים את views כדי למזער את פגמי ההיטל מחדש.

אם הפונקציה xrLocateSpatialContainerViewsEXT נקראת עבור קונטיינר מרחבי אחד או יותר שלא נמצא כרגע בקבוצת הרינדור הפעילה, זמן הריצה חייב להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT .

שימוש תקין (משתמע)

  • חובה להפעיל את התוסף XR_EXT_spatial_container_self_rendering לפני שקוראים לפונקציה xrLocateSpatialContainerViewsEXT
  • ‫ session חייב להיות כינוי תקין של XrSession
  • ‫ locateInfo חייב להיות מצביע למבנה XrSpatialContainerViewsLocateInfoEXT תקין
  • viewStates חייב להיות מצביע למערך של מבני viewStateCount XrSpatialContainerViewStateEXT
  • ‫ views חייב להיות מצביע למערך של מבני viewCount XrView
  • ‫ הפרמטר viewStateCount חייב להיות גדול מ-0
  • ‫ הפרמטר viewCount חייב להיות גדול מ-0

קודי החזרה

הצלחה

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

נכשל

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT
  • XR_ERROR_TIME_INVALID
  • XR_ERROR_VALIDATION_FAILURE
  • XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED

המבנה XrSpatialContainerViewsLocateInfoEXT מכיל את הפרמטרים לאיתור תצוגות באוסף של קונטיינרים מרחביים.

typedef struct XrSpatialContainerViewsLocateInfoEXT {
    XrStructureType                               type;
    const void*                                   next;
    XrTime                                        displayTime;
    uint32_t                                      viewLocateInfoCount;
    const XrSpatialContainerViewLocateInfoEXT*    viewLocateInfos;
} XrSpatialContainerViewsLocateInfoEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫displayTime הוא ה-XrTime שבו נמצאות התצוגות.
  • ‫viewLocateInfoCount הוא מספר הרשומות במערך viewLocateInfos.
  • ‫viewLocateInfos הוא מצביע למערך של מבני XrSpatialContainerViewLocateInfoEXT.

שימוש תקין (משתמע)

המבנה XrSpatialContainerViewLocateInfoEXT מכיל את הפרמטרים של מאגר מרחבי ספציפי כדי לאתר תצוגות.

typedef struct XrSpatialContainerViewLocateInfoEXT {
    XrStructureType            type;
    const void*                next;
    XrViewConfigurationType    viewConfigurationType;
    XrSpace                    space;
    XrSpatialContainerEXT      spatialContainer;
} XrSpatialContainerViewLocateInfoEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫viewConfigurationType הוא XrViewConfigurationType שמשמש למאגר המרחבי.
  • ‫space הוא ה-XrSpace שבו נמצאות התצוגות של הקונטיינר המרחבי.
  • ‫spatialContainer הוא נקודת האחיזה של XrSpatialContainerEXT.

האפליקציה יכולה לספק כל XrSpace חוקי ב-space , אבל מומלץ שהיא תספק את המרחב של המאגר המרחבי ל-XrSpatialContainerEXT התואם שצוין במבנה XrSpatialContainerViewLocateInfoEXT.

שימוש תקין (משתמע)

  • ‫ חובה להפעיל את התוסף XR_EXT_spatial_container_self_rendering לפני שמשתמשים ב-XrSpatialContainerViewLocateInfoEXT
  • type חייב להיות XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT
  • next חייב להיות NULL או מצביע תקין למבנה הבא בשרשרת מבנים
  • ‫ viewConfigurationType חייב להיות ערך XrViewConfigurationType תקין
  • ‫ space חייב להיות כינוי תקין ב-XrSpace
  • ‫ spatialContainer חייב להיות כינוי תקין של XrSpatialContainerEXT
  • גם space וגם spatialContainer חייבים להיווצר, להיות מוקצים או להישלף מאותו XrSession

המבנה XrSpatialContainerViewStateEXT מאוכלס על ידי קריאות ל-xrLocateSpatialContainerViewsEXT עם מידע על התאמת העיבוד לכל מאגר מרחבי.

typedef struct XrSpatialContainerViewStateEXT {
    XrStructureType            type;
    void*                      next;
    XrViewStateFlags           viewStateFlags;
    XrViewConfigurationType    viewConfigurationType;
    XrBool32                   shouldSubmitLayers;
    XrExtent2Di                recommendedImageExtent;
} XrSpatialContainerViewStateEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫viewStateFlags היא מסכת ביטים של XrViewStateFlags . לדגלים האלה יש אותה מטרה כמו ל-viewStateFlags במבנה הליבה של XrViewState.
  • ‫viewConfigurationType הוא XrViewConfigurationType שמציין את סוג הגדרת התצוגה שבה משתמש זמן הריצה של מאגר הנתונים המרחבי. זמני ריצה עשויים להפחית את הגדרת התצוגה למספר תצוגות נמוך יותר מזה שהתבקש.
  • ‫shouldSubmitLayers הוא XrBool32 שמוחזר על ידי זמן הריצה. אם XR_FALSE , האפליקציה צריכה להימנע משליחת קומפוזיציה למאגר המרחבי הזה כי הוא לא גלוי כרגע או שהוא במצב שבו לא נדרש רינדור.
  • ‫recommendedImageExtent הוא מבנה XrExtent2Di שמייצג את הרזולוציה המומלצת למאגר המרחבי.

כמו במיקום התצוגה של ליבת OpenXR, האפליקציה חייבת לבדוק את XrSpatialContainerViewStateEXT :: viewStateFlags כדי לוודא שהמיקום והכיוון תקינים ומתבצע אחריהם מעקב לפני השימוש בנתוני התצוגה לעיבוד.

האפליקציה צריכה לבדוק את shouldSubmitLayers ואת viewConfigurationType כדי להימנע מעיבוד של יותר ממה שמומלץ בזמן הריצה. כשהערך של shouldSubmitLayers הוא false, האפליקציה משנה את אופן העיבוד (rendering) שלה באופן הבא:

  • האפליקציה לא יכולה לקרוא את XrView :: fov התואם.
  • האפליקציה לא יכולה לקרוא את recommendedImageExtent .
  • האפליקציה לא אמורה לעבד לשרשראות החלפה (swapchains) ולשלוח שכבות קומפוזיציה למאגר המרחבי המתאים.
  • האפליקציה צריכה להגדיר את XrSpatialContainerLayerEXT :: retainPreviousSubmission כ-true. אם האפליקציה בוחרת לשלוח שכבות בכל זאת, סביבת זמן הריצה תקבע מה לעשות עם השכבות (למשל, סביבת זמן הריצה עשויה לבחור להשמיט אותן).

המאפיין recommendedImageExtent מיועד במפורש לשכבות שיעודכנו על סמך מיקום מאגר התגים או התצוגה של המשתמש. כשמעדכנים שכבות עם תוכן שתלוי במיקום של הקונטיינר המרחבי או בתצוגה של המשתמש (כמו תוכן תלת-ממדי רגיל), האפליקציה צריכה לעבד את התוכן לאזור התצוגה הקטן יותר במקום לגודל התצוגה המומלץ שמוגדר כברירת מחדל. כשמעדכנים שכבות עם תוכן שלא תלוי במיקום של מאגר המידע המרחבי או בתצוגה של המשתמש (כמו שכבות מרובעות סטטיות), האפליקציה יכולה להתעלם מהערכים האלה בלי בעיה. בשכבות שתלויות בתצוגה, recommendedImageExtent היא המלצה לאפליקציה מסביבת זמן הריצה שנועדה לצמצם את ההתחזות ולשפר את ביצועי העיבוד. האפליקציה יכולה לשלוח את התמונות ברזולוציה מלאה אם היא רוצה.

XrExtent2Di :: width ו-XrExtent2Di :: height של recommendedImageExtent חייבים תמיד להיות מספר שלם חיובי שקטן או שווה ל-XrViewConfigurationView :: recommendedImageRectWidth ול-XrViewConfigurationView :: recommendedImageRectHeight של XrViewConfigurationView להגדרת התצוגה הראשית של מאגר הנתונים המרחבי. אפליקציה לא אמורה ליצור מחדש swapchain רק בגלל ש-recommendedImageExtent השתנה, כי זה רמז דינמי לאפליקציה שמציין את XrSwapchainSubImage :: imageRect לשימוש ב-XrSwapchainSubImage של כל שכבות הקומפוזיציה ברזולוציה מלאה שהיא שולחת, ויכולה לשנות כל פריים.

שימוש תקין (משתמע)

הצגת מרחב העזר

מרחב ההתייחסות של התצוגה נשאר ללא שינוי, כמו שהוא בליבה של OpenXR. כמו בליבה, הוא לא מיועד לעיבוד.

שליחת שכבות באמצעות xrEndFrame

כדי לעבד קונטיינרים מרחביים, האפליקציה חייבת לספק ל-xrEndFrame רשימה של שכבות שמשויכות לקונטיינרים המרחביים שלהן. כדי לעשות את זה, משתמשים במבנה XrSpatialContainerLayerFrameEndInfoEXT.

typedef struct XrSpatialContainerLayerFrameEndInfoEXT {
    XrStructureType                      type;
    const void*                          next;
    uint32_t                             containerLayerCount;
    const XrSpatialContainerLayerEXT*    containerLayers;
} XrSpatialContainerLayerFrameEndInfoEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫containerLayerCount הוא מספר הרכיבים במערך containerLayers.
  • ‫containerLayers הוא מצביע למערך של מבני XrSpatialContainerLayerEXT.

המערך containerLayers מכיל XrSpatialContainerLayerEXT לכל מאגר מרחבי בקבוצת הרינדור הפעילה (המאגרים שמנוהלים בכל סשן על ידי xrBeginSpatialContainerRenderingEXT ו-xrEndSpatialContainerRenderingEXT). כל XrSpatialContainerLayerEXT מכיל רשימה של מצביעי XrCompositionLayerBaseHeader שמשויכים למאגר המרחבי הנתון. סביבות זמן ריצה עשויות לשלב קונטיינרים בכל סדר שהן בוחרות, ללא קשר לסדר של containerLayers . לדוגמה, סביבות זמן ריצה עשויות לשלב קונטיינרים על סמך העומק שלהם ביחס למשתמש, להגדיר קונטיינר מרחבי כשכבת רקע או "להצמיד" קונטיינר מרחבי כך שהוא תמיד יהיה למעלה, בלי קשר לעומק שלו. סביבות זמן ריצה עשויות לשלב שכבות באמצעות אסטרטגיות שונות למאגרים מרחביים במצבים מוגבלים או אימרסיביים. לדוגמה, סביבות זמן ריצה עשויות לבצע קומפוזיציה מראש של שכבות הקומפוזיציה של כל מאגר מרחבי מוגבל לשכבת סטריאו מרובעת אחת, שמשולבת עם כל המאגרים האחרים בשלב קומפוזיציה שני.

הערכים XrFrameEndInfo :: displayTime ו-XrFrameEndInfo :: environmentBlendMode יחולו על כל מאגרי הנתונים המרחביים שסופקו ב-XrSpatialContainerLayerFrameEndInfoEXT .

כשמעבירים את המבנה הזה אל xrEndFrame על ידי שרשור אל XrFrameEndInfo , מתווספים מקרי השגיאה הבאים על סמך קבוצת הרינדור הפעילה:

  • אם יש הפניה למאגר מרחבי מיותר מרכיב אחד של containerLayers , זמני הריצה חייבים להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_DUPLICATE_EXT .
  • אם קונטיינר מרחבי בקבוצת הרינדור הפעילה לא מקושר לאלמנט של containerLayers , זמני הריצה חייבים להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT .
  • אם מאגר מרחבי שאליו מפנה containerLayers לא שייך לקבוצת הרינדור הפעילה, זמני הריצה חייבים להחזיר את XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT .

בנוסף, אם יש קונטיינרים מרחביים בקבוצת הרינדור הפעילה והמבנה הזה לא משורשר אל XrFrameEndInfo , סביבות זמן הריצה חייבות להחזיר את הערך XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT .

בכל אחד ממקרי השגיאה שלמעלה, סביבת זמן הריצה לא צריכה לעבד תוכן לאף מאגר מרחבי.

אם אין קונטיינרים מרחביים בקבוצת הרינדור הפעילה, אפליקציה יכולה לקרוא ל-xrEndFrame כל עוד היא לא שולחת שכבות קומפוזיציה.

שימו לב שאפשר לשלוח שרשראות החלפה נפרדות לכמה קונטיינרים דרך שכבות במבנה תקין. לדוגמה, שכבת Quad שעברה רינדור דרך שרשרת החלפה אחת שנשלחה לכמה קונטיינרים מרחביים. המקרה הזה מטופל באופן אחיד עם עיבוד אחר: זמן הריצה חייב לעבד את המרובע בכל המכלים המרחביים האלה.

שימוש תקין (משתמע)

  • ‫ חובה להפעיל את התוסף XR_EXT_spatial_container_self_rendering לפני שמשתמשים ב-XrSpatialContainerLayerFrameEndInfoEXT
  • type חייב להיות XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT
  • next חייב להיות NULL או מצביע תקין למבנה הבא בשרשרת מבנים
  • ‫ containerLayers חייב להיות מצביע למערך של מבני XrSpatialContainerLayerEXT תקינים של containerLayerCount
  • ‫ הפרמטר containerLayerCount חייב להיות גדול מ-0

המבנה XrSpatialContainerLayerEXT מקבץ שכבות קומפוזיציה סטנדרטיות ומשייך אותן לקונטיינר מרחבי ספציפי.

typedef struct XrSpatialContainerLayerEXT {
    XrStructureType                               type;
    const void*                                   next;
    XrSpatialContainerEXT                         spatialContainer;
    XrBool32                                      retainPreviousSubmission;
    uint32_t                                      layerCount;
    const XrCompositionLayerBaseHeader* const*    layers;
} XrSpatialContainerLayerEXT;

תיאור המשתמש

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫spatialContainer הוא ה-XrSpatialContainerEXT שמזהה את מאגר היעד.
  • ‫retainPreviousSubmission הוא XrBool32 . אם XR_TRUE , סביבת זמן הריצה תשמור את הפריים האחרון שנשלח למאגר המרחבי הזה.
  • ‫layerCount הוא מספר שכבות הקומפוזיציה במערך layers.
  • ‫layers הוא מצביע למערך של מצביעי XrCompositionLayerBaseHeader.

כאשר retainPreviousSubmission הוא XR_TRUE , זמן הריצה חייב לעשות שימוש חוזר בשכבות הקומפוזיציה ובתוכן התמונה של שרשרת ההחלפה כפי שננעל במהלך הקריאה האחרונה של xrEndFrame שבה retainPreviousSubmission היה XR_FALSE . שינויים שבוצעו לאחר מכן בשרשראות החלפה שמשמשות שכבות שנשמרו לא צריכים להשתקף בפלט שעבר רינדור.

בשכבות שנשלחות למכל מרחבי נפרד (רינדור בתוך המכל), סביבת זמן הריצה חייבת לפעול לפי הכללים שכבר צוינו לגבי סדר הקומפוזיציה של השכבות. כלומר, השכבות בתוך מאגרים חייבות להיות משורטטות באותו סדר שבו הן צוינו, ומורכבות באמצעות אלגוריתם הצייר.

"ניקוי" של מאגר מרחבי מתייחס להסרה של כל התוכן ממאגר מרחבי, כך ששום דבר לא מוצג במאגר הזה בפריים הנוכחי. סביבות זמן ריצה חייבות להתייחס לכך באופן שווה ערך לאפליקציה ששולחת שחור שקוף (כל הביטים 0) לכל פיקסל בתוך מאגר התגים. "שמירה" של קונטיינר מרחבי מתייחסת לכך שסביבת זמן הריצה ממשיכה להציג את קבוצת השכבות האחרונה שנשלחה עבור הקונטיינר הזה.

בכל מאגר מרחבי, האפליקציה יכולה לציין אם לשלוח שכבות חדשות, לשמור את השליחה הקודמת או לנקות את המאגר המרחבי:

  • כדי לשלוח שכבות חדשות, האפליקציה מספקת layerCount שאינו אפס ומצביע layers חוקי.
  • כדי לנקות מאגר מרחבי, הערך של layerCount ברשומה שלו חייב להיות 0 והערך של retainPreviousSubmission חייב להיות XR_FALSE .
  • כדי לשמור את השכבות ואת תמונות ה-swapchain שנשלחו לאחרונה (שמירה), הערך של layerCount עבור הרשומה שלו חייב להיות 0 והערך של retainPreviousSubmission חייב להיות XR_TRUE .

אמצעי הבקרה המפורש הזה לכל מאגר מבטיח שהכוונה של האפליקציה תועבר בצורה ברורה בכל פריים.

אם retainPreviousSubmission הוא XR_TRUE ו-layerCount הוא לא 0, זמן הריצה חייב להחזיר את הערך XR_ERROR_VALIDATION_FAILURE .

אם XrSpatialContainerCompositionLayerViewConfigurationEXT לא משורשר ל-XrCompositionLayerProjection שהוא חלק ממכל מרחבי, זמן הריצה חייב להחזיר את XR_ERROR_VALIDATION_FAILURE . המבנה הזה רלוונטי רק לשכבות XrCompositionLayerProjection. אם היא משורשרת לסוגי שכבות אחרים (למשל שכבות מרובעות או גליליות), זמן הריצה חייב להחזיר את הערך XR_ERROR_VALIDATION_FAILURE .

שימוש תקין (משתמע)

הגדרת תצוגה לשכבות של היטלים

המבנה XrSpatialContainerCompositionLayerViewConfigurationEXT משמש לציון הגדרת התצוגה שמשמשת לעיבוד של שכבת היטל למאגר מרחבי.

typedef struct XrSpatialContainerCompositionLayerViewConfigurationEXT {
    XrStructureType            type;
    const void*                next;
    XrViewConfigurationType    viewConfigurationType;
} XrSpatialContainerCompositionLayerViewConfigurationEXT;

תיאור המשתמש

כששולחים XrCompositionLayerProjection למאגר מרחבי, האפליקציה חייבת לציין באיזו הגדרת תצוגה נעשה שימוש כדי לעבד את השכבה. זה הכרחי כי האפליקציה יכולה לבחור בכל פריים אם לעבד באמצעות הגדרת התצוגה הראשית של מאגר המידע המרחבי או הגדרת התצוגה המומלצת של זמן הריצה, אם יש כזו.

כש-XrSpatialContainerCompositionLayerViewConfigurationEXT משורשר, האפליקציה חייבת לוודא ש-XrCompositionLayerProjection :: viewCount הוא מספר צפיות תקין ל-XrViewConfigurationType שצוין במבנה המשורשר. ה-viewConfigurationType שצוין במבנה המשורשר חייב להיות XrSpatialContainerBeginInfoEXT :: primaryViewConfigurationType שצוין כשהקונטיינר התחיל, או סוג הגדרת התצוגה המופחתת שהוחזר על ידי זמן הריצה ב-XrSpatialContainerViewStateEXT , או ערכים נוספים שהופעלו באמצעות תוסף.

שימוש תקין (משתמע)

התנהגות של חיתוך פיקסלים

האפליקציות צריכות להודיע לסביבת זמן הריצה אם הן מעבדות פיקסלים מחוץ לגבולות של מאגר מרחבי או לא, על ידי שרשור של XrSpatialContainerLayerVolumeClippingEXT בזמן שליחת שכבות הקומפוזיציה.

typedef struct XrSpatialContainerLayerVolumeClippingEXT {
    XrStructureType                        type;
    const void*                            next;
    XrSpatialContainerVolumeClippingEXT    volumeClipping;
} XrSpatialContainerLayerVolumeClippingEXT;

תיאור המשתמש

המבנה הזה משמש כרמז אם האפליקציה מעבדת פיקסלים מחוץ לגבולות של קונטיינר מרחבי. כשמאגר מרחבי נמצא במצב אימרסיבי, הגבולות הם אינסופיים ולכן לרמז הזה אין משמעות.

במכלים מרחביים מוגבלים שמשתמשים ברינדור עצמי, זמן הריצה צריך להביא בחשבון גם את גבולות הנפח התלת-ממדי וגם את גבולות הפיקסלים הדו-ממדיים. גבולות הנפח התלת-ממדי מוחזרים מ-xrGetSpatialContainerBoundsEXT . גבולות הפיקסלים הדו-ממדיים הם ההיטל של גבולות הנפח התלת-ממדיים על כל מסך במערכת.

סביבות זמן ריצה חייבות למחוק פיקסלים מתמונות של שרשרת החלפה (swapchain) שנמצאות מחוץ לגבולות הפיקסלים הדו-ממדיים, אבל סביבות זמן ריצה לא יכולות למחוק פיקסלים שנמצאים בתוך גבולות הפיקסלים הדו-ממדיים אבל מחוץ לגבולות הנפח התלת-ממדי. אפשר להשתמש באפקטים סטריאוסקופיים שבהם נראה שהתוכן חורג מהגבולות של הנפח התלת-ממדי של הקונטיינר או מופיע לפניהם. אפליקציות יכולות להשמיט פיקסלים מחוץ לגבולות הנפח התלת-ממדי של מאגר מרחבי מוגבל כדי לצמצם פרדוקסים של עומק, וצריכות להגדיר את volumeClipping על סמך האופן שבו הן עושות זאת. פרדוקסים של עומק גורמים לעיתים קרובות למאמץ בעיניים ולאי-נוחות למשתמשים.

סביבות זמן ריצה עשויות להשתמש ב-volumeClipping כדי לשנות את האופן שבו הן מציגות קונטיינר מרחבי מסוים. לדוגמה, אם המדיניות מוגדרת לערך XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT, סביבת זמן ריצה יכולה לעבד את הפנים האחוריות של גבולות הנפח התלת-ממדי, מה שיגרום לפרדוקסים של עומק אם המאגר המרחבי ישרטט פיקסלים מאחורי גבולות הנפח התלת-ממדי של המאגר.

יכול להיות שתוספים עתידיים יאפשרו חיתוך על סמך גבולות הנפח התלת-ממדי אם יישלח מידע על העומק.

שימוש תקין (משתמע)

פקודות חדשות

מבנים חדשים

קבועי Enum חדשים

  • XR_EXT_SPATIAL_CONTAINER_SELF_RENDERING_EXTENSION_NAME
  • XR_EXT_spatial_container_self_rendering_SPEC_VERSION
  • הרחבת XrResult :

    • XR_ERROR_SPATIAL_CONTAINER_DUPLICATE_EXT
    • XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT
    • XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT
    • XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT
    • XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT
  • הרחבה של XrSpatialContainerGraphicsPresentationEXT :

    • XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
  • הרחבה של XrStructureType :

    • XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT
    • XR_TYPE_SPATIAL_CONTAINER_COMPOSITION_LAYER_VIEW_CONFIGURATION_EXT
    • XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT
    • XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT
    • XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT
    • XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT
    • XR_TYPE_SPATIAL_CONTAINER_VIEWS_LOCATE_INFO_EXT
    • XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT
    • XR_TYPE_SPATIAL_CONTAINER_VIEW_STATE_EXT

דוגמאות קוד

// Example: Complete lifecycle, view location, and frame submission for spatial containers
PFN_xrBeginSpatialContainerRenderingEXT xrBeginSpatialContainerRenderingEXT; // previously initialized
PFN_xrEndSpatialContainerRenderingEXT xrEndSpatialContainerRenderingEXT; // previously initialized
PFN_xrLocateSpatialContainerViewsEXT xrLocateSpatialContainerViewsEXT; // previously initialized

XrSession session; // previously initialized

// We want to update this container
XrSpatialContainerEXT containerA; // previously initialized with XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
XrSpace containerASpace; // previously initialized

// We want to retain this container
XrSpatialContainerEXT containerB; // previously initialized with XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
XrSpace containerBSpace; // previously initialized

// 1. Add to active render set when the app is ready to start submitting layers
XrSpatialContainerBeginInfoEXT beginInfoA {
  .type = XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT,
  .spatialContainer = containerA,
  .primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
};
CHK_XR(xrBeginSpatialContainerRenderingEXT(session, &beginInfoA));

XrSpatialContainerBeginInfoEXT beginInfoB {
  .type = XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT,
  .spatialContainer = containerB,
  .primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
};
CHK_XR(xrBeginSpatialContainerRenderingEXT(session, &beginInfoB));

// ... Frame Loop ...


XrTime displayTime; // returned from xrWaitFrame

const std::vector<XrSpatialContainerEXT> containers = {containerA, containerB};
const std::vector<XrSpace> containerSpaces = {containerASpace, containerBSpace};
uint32_t containerCount = static_cast<uint32_t>(containers.size());

// 2. Setup individual locate info for each container
std::vector<XrSpatialContainerViewLocateInfoEXT> containerLocateInfos(containerCount, {
  .type = XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT,
});

for (uint32_t i = 0; i < containerCount; ++i) {
    containerLocateInfos[i].viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
    containerLocateInfos[i].space = containerSpaces[i]; // Recommended to use container's own space
    containerLocateInfos[i].spatialContainer = containers[i];
}

// Setup bulk locate info
XrSpatialContainerViewsLocateInfoEXT locateInfo {
  .type = XR_TYPE_SPATIAL_CONTAINER_VIEWS_LOCATE_INFO_EXT,
  .displayTime = displayTime,
  .viewLocateInfoCount = containerCount,
  .viewLocateInfos = containerLocateInfos.data(),
};

// Prepare states to be populated by the runtime
std::vector<XrSpatialContainerViewStateEXT> viewStates(containerCount, {
  .type = XR_TYPE_SPATIAL_CONTAINER_VIEW_STATE_EXT,
});

// Call the dedicated locate views function
// We know the required view count is 2 per container for STEREO
const uint32_t viewsPerConfig = 2;
uint32_t totalViewCount = containerCount * viewsPerConfig;
std::vector<XrView> views(totalViewCount, {.type = XR_TYPE_VIEW});

CHK_XR(xrLocateSpatialContainerViewsEXT(session, &locateInfo, containerCount, viewStates.data(), totalViewCount, views.data()));

// Process results
for (uint32_t i = 0; i < containerCount; ++i) {
    XrBool32 shouldSubmitLayers = viewStates[i].shouldSubmitLayers;
    XrExtent2Di recommendedImageExtent = viewStates[i].recommendedImageExtent;
    XrViewConfigurationType viewConfigurationType = viewStates[i].viewConfigurationType;
    bool isDecayedToMono = (viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO);
    if (shouldSubmitLayers) {
        // App is expected to also verify viewStates[i].viewStateFlags has valid orientation/position bits before rendering
        XrView& leftView = views[i * viewsPerConfig];
        XrView& rightView = views[i * viewsPerConfig + 1];
        // If isDecayedToMono is true, left and right will be identical.
    } else {
        // Skip layer submission but retain previous submission when calling
        // xrEndFrame.
    }
}

// 3. Setup projection layer for container A
XrCompositionLayerProjection projectionLayer = {.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION};
// ... standard projection layer setup (space, viewCount, views, etc.) ...

// Specify which view configuration was used to render this specific layer
XrSpatialContainerCompositionLayerViewConfigurationEXT containerViewConfig {
  .type = XR_TYPE_SPATIAL_CONTAINER_COMPOSITION_LAYER_VIEW_CONFIGURATION_EXT,
  // Even if the runtime decayed to MONO, we indicate what we actually rendered
  .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
};

// Chain it to the projection layer
projectionLayer.next = &containerViewConfig;
const XrCompositionLayerBaseHeader* layersA[1] = {reinterpret_cast<const XrCompositionLayerBaseHeader*>(&projectionLayer)};

// Note: In a real app, you are required to submit ALL active containers in the render set.

XrSpatialContainerLayerVolumeClippingEXT containerClippingA = {
  .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT,
  // Set volumeClipping appropriately for the rendering done.
  .volumeClipping = XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT,
};

// Setup container A (Update with new pixels)
XrSpatialContainerLayerEXT containerLayerA {
  .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT,
  .next = &containerClippingA,
  .spatialContainer = containerA,
  .retainPreviousSubmission = XR_FALSE,
  .layerCount = 1,
  .layers = layersA,
};

XrSpatialContainerLayerVolumeClippingEXT containerClippingB {
  .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT,
  // Set volumeClipping appropriately for the rendering done.
  .volumeClipping = XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT,
};

// Setup container B (Explicitly retain previous frame)
XrSpatialContainerLayerEXT containerLayerB {
  .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT,
  .next = &containerClippingB,
  .spatialContainer = containerB,
  .retainPreviousSubmission = XR_TRUE,
  .layerCount = 0, // Required to be 0 when retaining
  .layers = nullptr,
};

// Aggregate all container layers
XrSpatialContainerLayerEXT containerLayers[] = { containerLayerA, containerLayerB };

XrSpatialContainerLayerFrameEndInfoEXT spatialEndInfo {
  .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT,
  .containerLayerCount = 2, // Must equal the number of active containers
  .containerLayers = containerLayers,
};

XrFrameEndInfo frameEndInfo {
  .type = XR_TYPE_FRAME_END_INFO,
  .next = &spatialEndInfo,
  .displayTime = displayTime,
  .environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND,
  .layerCount = 0, // MANDATORY: Must be 0 for self rendering extension
};

CHK_XR(xrEndFrame(session, &frameEndInfo));

// ... End Frame Loop ...

// 4. Remove from active render set when the container is destroyed or no longer needs rendering
XrSpatialContainerEndInfoEXT endInfoA {
  .type = XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT,
  .spatialContainer = containerA,
};
CHK_XR(xrEndSpatialContainerRenderingEXT(session, &endInfoA));

XrSpatialContainerEndInfoEXT endInfoB {
  .type = XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT,
  .spatialContainer = containerB,
};
CHK_XR(xrEndSpatialContainerRenderingEXT(session, &endInfoB));

היסטוריית הגרסאות

  • גרסה 1, 06.08.2026 (Lachlan Ford)

    • תיאור התוסף הראשוני