Skip to content

Instantly share code, notes, and snippets.

@fredemmott
Last active January 23, 2024 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fredemmott/f5f67222931039f8da83940e798c26a6 to your computer and use it in GitHub Desktop.
Save fredemmott/f5f67222931039f8da83940e798c26a6 to your computer and use it in GitHub Desktop.

XR_FREDEMMOTT_reflection

Previously XR_FREDEMMOTT_structure_type_sizes

Document version: v2024.01.23.03

Status: Initial draft/RFC. Not started formal process

New structures

This extension would add two structures.

struct XrStructureTypeReflectionFREDEMMOTT {
  XrStructureType type; // = XR_TYPE_STRUCTURE_TYPE_REFLECTION_FREDEMMOTT
  void* next;
  XrStructureType reflectedType; // varies
  size_t size;
  char name[XR_MAX_STRUCTURE_NAME_SIZE];
};
  • type is always XR_TYPE_STRUCTURE_TYPE_REFLECTION_FREDEMMOTT
  • next is NULL or a pointer to the next structure in a structure chain. No such structures are currently defined.
  • reflectedType is theXrStructureType of a structure defined in the core specification or extneion
    • it MAY be XR_TYPE_STRUCTURE_TYPE_REFLECTION_FREDEMMOTT, if the name and size fields contain information on this structure
    • it MUST NOT be XR_TYPE_UNKNOWN or XR_STRUCTURE_TYPE_MAX_ENUM
  • size MUST equal the size (in bytes) of the structure specified by reflectedType; for example, if reflectedType is XR_TYPE_INSTANCE_CREATE_INFO, size MUST be equal to sizeof(XrInstanceCreateInfo)
  • name MUST be the null-terminated literal string defined for reflectedType in the core specification or extension, in UTF-8 encoding; for example, if reflectedType is XR_TYPE_INSTANCE_CREATE_INFO, name MUST be "XR_TYPE_INSTANCE_CREATE_INFO"
struct XrReflectionFREDEMMOTT {
  XrStructureType type; // = XR_TYPE_REFLECTION_FREDEMMOTT
  void* next;
  uint32_t structureCount;
  XrStructureTypeReflectionFREDEMMOTT* structures;
};
  • type is always XR_TYPE_REFLECTION_FREDEMMOTT
  • next is NULL or a pointer to the next structure in a structure chain
  • structureCount is the number of elements in the structures array
  • structures is an array of XrStructureTypeReflectionFREDEMMOTT elements

XrReflectionFREDEMMOTT is intended to be passed as part of the next chain of an XrCreateInstanceInfo; if present:

  • implementations of this extension MUST merge the included metadata with their own in their implementations of xrStructureTypeToString()
    • for example, if the runtime does not recognize XrStructureType with integer value n it would usually set the buffer to "XR_UNKNOWN_STRUCTURE_TYPE_*n*. If metadata for n was provided to xrCreateInstance, the runtime should instead set the buffer to the value provided in the metadata
  • implementations of this extension MUST merge the included metadata with their own in their implementations of xrStructureTypeToSizeFREDEMMOTT()
  • structures SHOULD NOT contain multiple structures with the same value of reflectedType
  • implementations MAY return XR_ERROR_VALIDATION_FAILURE from xrCreateInstance if an element of structures contains a recognized XrStructureType, but differing size or name

New functions

This extension would add a single function:

XrResult xrStructureTypeToSizeFREDEMMOTT(XrInstance instance, XrStructureType type, size_t* size);
  1. It MUST return XR_ERROR_VALIDATION_FAILURE if type is XR_TYPE_UNKNOWN, or greater than or equal to XR_STRUCTURE_TYPE_MAX_ENUM
  2. It MAY return XR_ERROR_HANDLE_INVALID if instance is not a valid instance
  3. If type is recognized as a value from the OpenXR core specification or an extension, it MUST set *size to the size of the OpenXR structure with that type and return XR_SUCCESS
  4. Otherwise, if metadata for type was provided in an XrReflectionFREDEMMOTT structure in the next chain, it MUST set *size to the size of the OpenXR structure with that type and return XR_SUCCESS
  5. In all other cases:
    • API layer implementations MUST delegate unrecognized type values to the next API layer, or the runtime if it is the last API layer
    • Runtime implementations MUST return XR_ERROR_FEATURE_UNSUPPORTED

For example, xrStructureTypeToSizeFREDEMMOTT(XR_TYPE_INSTANCE_CREATE_INFO, &size) should set size to sizeof(XrInstanceCreateInfo)

Example implementation

#include <openxr/openxr.h>
#include <openxr/openxr_reflection.h>

struct InstanceImpl {
  // Optionally populated from data in `XrReflectionFREDEMMOTT`, passed in the
  // `next` chain of `XrInstanceCreateInfo`
  std::unordered_map<XrStructureType, size_t> mSizes;
  // ...
};
std::unordered_map<XrInstance, InstanceImpl> gInstances;

typedef XrResult (*PFN_XrStructureTypeToSizeFREDEMMOTT)(XrInstance, XrStructureType, size_t*);

XrResult xrStructureTypeToSizeFREDEMMOTT(
  XrInstance instance,
  XrStructureType xrStructureType,
  size_t* size) {
  if (!gInstances.contains(instance)) {
    return XR_ERROR_HANDLE_INVALID;
  }
  if (
    xrStructureType == XR_TYPE_UNKNOWN
    || xrStructureType >= XR_STRUCTURE_TYPE_MAX_ENUM) {
    return XR_ERROR_VALIDATION_FAILURE;
  }
  switch (xrStructureType) {
#define X(xrStruct, val) \
  case val: \
    *size = sizeof(xrStruct); \
    return XR_SUCCESS;
    XR_LIST_STRUCTURE_TYPES(X)
#undef X
    default:
      if (gInstances.at(instance).mSizes.contains(xrStructureType)) {
        return gInstances.at(instance).mSizes.at(xrStructureType);
      }
#ifdef API_LAYER_IMPLEMENTATION
      if (gPFN_XrStructureTypeToSizeFREDEMMOTT) {
        return gPFN_XrStructureTypeToSizeFREDEMMOTT(xrStructureType, size);
      }
#else
      return XR_ERROR_FEATURE_UNSUPPORTED;
#endif
  }
}

Modified functions

xrCreateInstance

Implementations MAY return XR_ERROR_VALIDATION_FAILURE if the next chain of XrCreateInstanceInfo contains an invalid XrReflectionFREDEMMOTT structure.

xrStructureTypeToString

  1. If the structure type was defined in the runtime's OpenXR API version, it MAY return the literal string defined for the provided numeric value in the core spec or extension. (e.g. the value of XR_TYPE_INSTANCE_CREATE_INFO results in the string "XR_TYPE_INSTANCE_CREATE_INFO")
  2. Otherwise, if the implementation supports XR_FREDEMMOTT_reflection and metadata for this structure was provided in an XrReflectionFREDEMMOTT structure in the next chain of XrInstanceCreateInfo, it SHOULD return the name string included in that metadata
  3. Otherwise, it MUST return XR_UNKNOWN_STRUCTURE_TYPE_ concatenated with the structure type number expressed as a decimal number.

If this extension is not supported, the behavior of (1) and (3) is intended to be identical to existing behavior

Motivation

This function is to better support API layers that need to modify an input next chain. For reading, they can be considered a chain of XrBaseInStructure*, however this is unsuitable for modification, as the next member of these is const.

While an API can easily prepend an entry to the next chain, they can not modify existing entries without copying every preceding entry in the chain, and updating their next pointers to point to the copies.

While this does not require understanding all the entries in the next chain, it does require knowing the size of any next structures passed by the application or higher layers.

The included modifications to xrStructureTypeToString() and corresponding name metadata are not essential, but have similar 'top-down' usage.

Why an extension?

As shown in the example implementation, it's not overly-problematic for API layers to implement this themselves; however, this unnecessarily limits them to being able to handle next structures that:

  • were defined in the version of the OpenXR SDK they were built against
  • were enabled by the combination of XR_USE_ flags and headers they chose to use

Modifying a next structure requires the ability to copy and modify all preceding next structure (at least the next pointer in these structures), so if an API layer does not use a particular set of struct type, that does not remove the need to be able to copy it, which requires obtaining the size of the structure from its' XrStructureType.

This extension allows API layers to correctly handle next structures that were not defined in the OpenXR API version they were built against.

Usage guidelines

Code that needs to use the results of this function should include code similar to the example implementation, even if they do not add support for additional structures.

This will potentially allow them to handle next structures that are unrecognized by lower layers or the runtime if built against a newer SDK, or if this extension is not implemented by the runtime or lower API layers.

Limitations

Conformant handling of next chains in API layers requires applications to adopt this extension, as well as API layers that implement extensions.

  • as this functionality is required for OpenXR API layers to handle next chains in a conformant manner, providing structure metadata to xrCreateInstance() should be a core requirement of a future revision of OpenXR
    • this should be required both for application developers, and for the developers of API layers that implement extensions
  • a helper should be provided to create and populate XrStructureTypeReflectionFREDEMMOTT and XrReflectionFREDEMMOTT structures for use with xrCreateInstance(), or to wrap xrCreateInstance() putting the metadata at the start of the next chain
  • as application developers often update the OpenXR headers without the updating the rest of the SDK, this helper should be entirely defined in the headers, e.g. with macros

Version history

  • v2024.01.22.02-03: typos etc
  • v2024.01.22.04: add 'limitations' section
  • v2024.01.22.05: typos etc
  • v2024.01.23.01: add XrReflectionFREDEMMOTT and XrStructureTypeReflectionFREDEMMOTT
  • v2024.01.23.02: instance is now required for correct behavior of xrStructureTypeToSizeFREDEMMOTT()
  • v2024.01.23.03: API layers that implement extensions should also be required to implement this in a future version of OpenXR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment