上传YomovSDK

This commit is contained in:
Sora丶kong
2026-03-03 03:15:46 +08:00
parent 9096da7e6c
commit eb97f31065
6477 changed files with 1932208 additions and 3 deletions

View File

@@ -0,0 +1,621 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine.XR.OpenXR.NativeTypes;
using UnityEngine.XR.OpenXR.Features.Extensions;
using UnityEngine.XR.OpenXR.Features.Extensions.PerformanceSettings;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.XR.OpenXR.Features;
using UnityEditor.Build;
#endif
[assembly: InternalsVisibleTo("Unity.XR.OpenXR.Tests")]
[assembly: InternalsVisibleTo("Unity.XR.OpenXR.Tests.Editor")]
namespace UnityEngine.XR.OpenXR.Features.Mock
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "Mock Runtime",
BuildTargetGroups = new[] {UnityEditor.BuildTargetGroup.Standalone, UnityEditor.BuildTargetGroup.Android},
Company = "Unity",
Desc = "Mock runtime extension for automated testing.",
DocumentationLink = Constants.k_DocumentationURL,
#if !OPENXR_USE_KHRONOS_LOADER
CustomRuntimeLoaderBuildTargets = new[] { UnityEditor.BuildTarget.StandaloneWindows64, UnityEditor.BuildTarget.StandaloneOSX, UnityEditor.BuildTarget.Android },
#endif
OpenxrExtensionStrings = MockRuntime.XR_UNITY_null_gfx + " " + XR_UNITY_android_present,
Version = "0.0.2",
FeatureId = featureId)]
#endif
/// <summary>
/// OpenXR Mock Runtime
/// </summary>
public class MockRuntime : OpenXRFeature
{
/// <summary>
/// Script events that are possible to subscribe to.
/// </summary>
public enum ScriptEvent
{
/// <summary>
/// Dummy script event.
/// </summary>
Unknown,
/// <summary>
/// EndFrame script event.
/// </summary>
EndFrame,
/// <summary>
/// HapticImpulse script event.
/// </summary>
HapticImpulse,
/// <summary>
/// HapticStop script event.
/// </summary>
HapticStop
}
/// <summary>
/// Delegate invoked on ScriptEvents
/// </summary>
/// <param name="evt">ScriptEvent invoked.</param>
/// <param name="param">Parameters of the script event.</param>
public delegate void ScriptEventDelegate(ScriptEvent evt, ulong param);
/// <summary>
/// Delegate invoked before function calls.
/// </summary>
/// <param name="functionName">The OpenXR function name.</param>
/// <returns>The XrResult of the callback.</returns>
public delegate XrResult BeforeFunctionDelegate(string functionName);
/// <summary>
/// Delegate invoked after function calls.
/// </summary>
/// <param name="functionName">The OpenXR function name.</param>
/// <param name="result">The XrResult of the function.</param>
public delegate void AfterFunctionDelegate(string functionName, XrResult result);
private static Dictionary<string, AfterFunctionDelegate> s_AfterFunctionCallbacks = null;
private static Dictionary<string, BeforeFunctionDelegate> s_BeforeFunctionCallbacks = null;
/// <summary>
/// Subscribe delegates to ScriptEvents.
/// </summary>
public static event ScriptEventDelegate onScriptEvent;
/// <summary>
/// The feature id string. This is used to give the feature a well known id for reference.
/// </summary>
public const string featureId = "com.unity.openxr.feature.mockruntime";
/// <summary>
/// Don't fail to build if there are validation errors.
/// </summary>
public bool ignoreValidationErrors = false;
/// <summary>
/// Return the singleton instance of the Mock Runtime feature.
/// </summary>
public static MockRuntime Instance => OpenXRSettings.Instance.GetFeature<MockRuntime>();
[AOT.MonoPInvokeCallback(typeof(ScriptEventDelegate))]
private static void ReceiveScriptEvent(ScriptEvent evt, ulong param) => onScriptEvent?.Invoke(evt, param);
[AOT.MonoPInvokeCallback(typeof(BeforeFunctionDelegate))]
private static XrResult BeforeFunctionCallback(string function)
{
var callback = GetBeforeFunctionCallback(function);
if (null == callback)
return XrResult.Success;
return callback(function);
}
[AOT.MonoPInvokeCallback(typeof(BeforeFunctionDelegate))]
private static void AfterFunctionCallback(string function, XrResult result)
{
var callback = GetAfterFunctionCallback(function);
if (null == callback)
return;
callback(function, result);
}
/// <summary>
/// Set the callbacks to call before and after the given OpenXR function is called within the Mock Runtime
///
/// Note that since some OpenXR functions are called from within the graphics thread that care should
/// be taken to maintain thread safety from within the callbacks.
///
/// Note that function callbacks can be set prior to the MockRuntime being initialized but will be
/// reset when the mock runtime is shutdown.
/// </summary>
/// <param name="function">OpenXR function name</param>
/// <param name="beforeCallback">Callback to call before the OpenXR function is called (null to clear)</param>
/// <param name="afterCallback">Callback to call after the OpenXR function is called (null to clear)</param>
public static void SetFunctionCallback(string function, BeforeFunctionDelegate beforeCallback, AfterFunctionDelegate afterCallback)
{
if (beforeCallback != null)
{
if (null == s_BeforeFunctionCallbacks)
s_BeforeFunctionCallbacks = new Dictionary<string, BeforeFunctionDelegate>();
s_BeforeFunctionCallbacks[function] = beforeCallback;
}
else if (s_BeforeFunctionCallbacks != null)
{
s_BeforeFunctionCallbacks.Remove(function);
if (s_BeforeFunctionCallbacks.Count == 0)
s_BeforeFunctionCallbacks = null;
}
if (afterCallback != null)
{
if (null == s_AfterFunctionCallbacks)
s_AfterFunctionCallbacks = new Dictionary<string, AfterFunctionDelegate>();
s_AfterFunctionCallbacks[function] = afterCallback;
}
else if (s_AfterFunctionCallbacks != null)
{
s_AfterFunctionCallbacks.Remove(function);
if (s_AfterFunctionCallbacks.Count == 0)
s_AfterFunctionCallbacks = null;
}
MockRuntime_RegisterFunctionCallbacks(
s_BeforeFunctionCallbacks != null ? BeforeFunctionCallback : (BeforeFunctionDelegate)null,
s_AfterFunctionCallbacks != null ? AfterFunctionCallback : (AfterFunctionDelegate)null);
}
/// <summary>
/// Set a callback to call before the given OpenXR function is called within the Mock Runtime
///
/// Note that since some OpenXR functions are called from within the graphics thread that care should
/// be taken to maintain thread safety from within the callbacks.
///
/// Note that function callbacks can be set prior to the MockRuntime being initialized but will be
/// reset when the mock runtime is shutdown.
/// </summary>
/// <param name="function">OpenXR function name</param>
/// <param name="beforeCallback">Callback to call before the OpenXR function is called (null to clear)</param>
public static void SetFunctionCallback(string function, BeforeFunctionDelegate beforeCallback) =>
SetFunctionCallback(function, beforeCallback, GetAfterFunctionCallback(function));
/// <summary>
/// Set a callback to call before the given OpenXR function is called within the Mock Runtime
/// </summary>
/// <param name="function">OpenXR function name</param>
/// <param name="afterCallback">Callback to call after the OpenXR function is called (null to clear)</param>
public static void SetFunctionCallback(string function, AfterFunctionDelegate afterCallback) =>
SetFunctionCallback(function, GetBeforeFunctionCallback(function), afterCallback);
/// <summary>
/// Return the callback set to be called before the given OpenXR function is called
/// </summary>
/// <param name="function">OpenXR function name</param>
/// <returns>Callback or null if no callback is set</returns>
public static BeforeFunctionDelegate GetBeforeFunctionCallback(string function)
{
if (null == s_BeforeFunctionCallbacks)
return null;
if (!s_BeforeFunctionCallbacks.TryGetValue(function, out var callback))
return null;
return callback;
}
/// <summary>
/// Return the callback set to be called after the given OpenXR function is called
/// </summary>
/// <param name="function">OpenXR function name</param>
/// <returns>Callback or null if no callback is set</returns>
public static AfterFunctionDelegate GetAfterFunctionCallback(string function)
{
if (null == s_AfterFunctionCallbacks)
return null;
if (!s_AfterFunctionCallbacks.TryGetValue(function, out var callback))
return null;
return callback;
}
/// <summary>
/// Remove all OpenXR function callbacks
/// </summary>
public static void ClearFunctionCallbacks()
{
s_BeforeFunctionCallbacks = null;
s_AfterFunctionCallbacks = null;
MockRuntime_RegisterFunctionCallbacks(null, null);
}
/// <summary>
/// Reset the MockRuntime testing settings back to defaults
/// </summary>
public static void ResetDefaults()
{
#if UNITY_INCLUDE_TESTS
var instance = Instance;
instance.TestCallback = (methodName, param) => true;
#endif
onScriptEvent = null;
ClearFunctionCallbacks();
}
/// <inheritdoc/>
protected internal override void OnInstanceDestroy(ulong instance)
{
#if UNITY_INCLUDE_TESTS
TestCallback(MethodBase.GetCurrentMethod().Name, instance);
XrInstance = 0ul;
if (!KeepFunctionCallbacks)
{
#endif
// When the mock runtime instance shuts down we remove any callbacks that
// were set up to ensure they do not linger around for the next usage of the mock runtime.
ClearFunctionCallbacks();
#if UNITY_INCLUDE_TESTS
}
#endif
}
#if UNITY_INCLUDE_TESTS
[NonSerialized] public Func<string, object, object> TestCallback = (methodName, param) => true;
public const string XR_UNITY_mock_test = "XR_UNITY_mock_test";
public const string XR_UNITY_null_gfx = "XR_UNITY_null_gfx";
public const string XR_UNITY_android_present = "XR_UNITY_android_present";
public ulong XrInstance { get; private set; } = 0ul;
public ulong XrSession { get; private set; } = 0ul;
private static bool s_KeepFunctionCallbacks;
internal static bool KeepFunctionCallbacks
{
get
{
return s_KeepFunctionCallbacks;
}
set
{
s_KeepFunctionCallbacks = value;
SetKeepFunctionCallbacks(value);
}
}
/// <summary>
/// Return the current session state of the MockRuntime
/// </summary>
public static XrSessionState sessionState => Internal_GetSessionState();
protected internal override IntPtr HookGetInstanceProcAddr(IntPtr func)
{
var ret = TestCallback(MethodBase.GetCurrentMethod().Name, func);
if (!(ret is IntPtr))
return HookCreateInstance(func);
return HookCreateInstance((IntPtr)ret);
}
protected internal override void OnSystemChange(ulong xrSystem)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSystem);
}
protected internal override bool OnInstanceCreate(ulong xrInstance)
{
var result = (bool)TestCallback(MethodBase.GetCurrentMethod().Name, xrInstance);
if (result)
XrInstance = xrInstance;
Internal_RegisterScriptEventCallback(ReceiveScriptEvent);
return result;
}
protected internal override void OnSessionCreate(ulong xrSession)
{
XrSession = xrSession;
TestCallback(MethodBase.GetCurrentMethod().Name, xrSession);
}
protected internal override void OnSessionBegin(ulong xrSession)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSession);
}
protected internal override void OnAppSpaceChange(ulong xrSpace)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSpace);
}
protected internal override void OnSessionEnd(ulong xrSession)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSession);
}
protected internal override void OnSessionDestroy(ulong session)
{
TestCallback(MethodBase.GetCurrentMethod().Name, session);
XrSession = 0ul;
}
protected internal override void OnSessionLossPending(ulong xrSession)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSession);
}
protected internal override void OnInstanceLossPending(ulong xrInstance)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrInstance);
}
protected internal override void OnSubsystemCreate()
{
TestCallback(MethodBase.GetCurrentMethod().Name, 0);
}
protected internal override void OnSubsystemStart()
{
TestCallback(MethodBase.GetCurrentMethod().Name, 0);
}
protected internal override void OnSessionExiting(ulong xrSession)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrSession);
}
protected internal override void OnSubsystemDestroy()
{
TestCallback(MethodBase.GetCurrentMethod().Name, 0);
}
protected internal override void OnSubsystemStop()
{
TestCallback(MethodBase.GetCurrentMethod().Name, 0);
}
protected internal override void OnFormFactorChange(int xrFormFactor)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrFormFactor);
}
protected internal override void OnEnvironmentBlendModeChange(XrEnvironmentBlendMode xrEnvironmentBlendMode)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrEnvironmentBlendMode);
}
protected internal override void OnViewConfigurationTypeChange(int xrViewConfigurationType)
{
TestCallback(MethodBase.GetCurrentMethod().Name, xrViewConfigurationType);
}
internal class XrSessionStateChangedParams
{
public int OldState;
public int NewState;
}
protected internal override void OnSessionStateChange(int oldState, int newState)
{
TestCallback(MethodBase.GetCurrentMethod().Name, new XrSessionStateChangedParams() {OldState = oldState, NewState = newState});
}
public static bool TransitionToState(XrSessionState state, bool forceTransition)
{
var instance = Instance;
if (instance.XrSession == 0)
return false;
return Internal_TransitionToState(state, forceTransition);
}
public static void ChooseEnvironmentBlendMode(XrEnvironmentBlendMode mode)
{
SetEnvironmentBlendMode(mode);
}
public static XrEnvironmentBlendMode GetXrEnvironmentBlendMode()
{
return GetEnvironmentBlendMode();
}
#if UNITY_EDITOR
protected internal override void GetValidationChecks(List<ValidationRule> results, BuildTargetGroup target)
{
foreach (var res in results)
{
var check = res.checkPredicate;
res.checkPredicate = () =>
{
if (enabled && ignoreValidationErrors)
return true;
return check();
};
}
TestCallback(MethodBase.GetCurrentMethod().Name, results);
}
#endif
#endif
const string extLib = "mock_api";
/// <summary>
/// Called to hook xrGetInstanceProcAddr.
/// </summary>
/// <param name="func">xrGetInstanceProcAddr native function pointer</param>
/// <returns>Function pointer that Unity will use to look up XR native functions.</returns>
[DllImport(extLib, EntryPoint = "MockRuntime_HookCreateInstance")]
public static extern IntPtr HookCreateInstance(IntPtr func);
/// <summary>
/// Keep function callbacks when resetting MockRuntime.
/// </summary>
/// <param name="value">True to keep callbacks.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_SetKeepFunctionCallbacks")]
public static extern void SetKeepFunctionCallbacks([MarshalAs(UnmanagedType.I1)] bool value);
/// <summary>
/// Set the runtime ViewPose.
/// </summary>
/// <param name="viewConfigurationType">The XrViewConfigurationType to use.</param>
/// <param name="viewIndex">The indexed view being set.</param>
/// <param name="position">Position of the view.</param>
/// <param name="orientation">Orientation of the view.</param>
/// <param name="fov">Field of View.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_SetView")]
public static extern void SetViewPose(XrViewConfigurationType viewConfigurationType, int viewIndex, Vector3 position, Quaternion orientation, Vector4 fov);
/// <summary>
/// Set the runtime ViewState.
/// </summary>
/// <param name="viewConfigurationType">The XrViewConfigurationType to use.</param>
/// <param name="viewStateFlags">The XrViewStateFlags to set.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_SetViewState")]
public static extern void SetViewState(XrViewConfigurationType viewConfigurationType, XrViewStateFlags viewStateFlags);
/// <summary>
/// Set the reference space to use at Runtime.
/// </summary>
/// <param name="referenceSpace">The type of reference space being set.</param>
/// <param name="position">Position of the space.</param>
/// <param name="orientation">Orientation of the space.</param>
/// <param name="locationFlags">XrSpaceLocationFlags for the space.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_SetReferenceSpace")]
public static extern void SetSpace(XrReferenceSpaceType referenceSpace, Vector3 position, Quaternion orientation, XrSpaceLocationFlags locationFlags);
/// <summary>
/// Set the reference space to use for input actions.
/// </summary>
/// <param name="actionHandle">Handle to the input action.</param>
/// <param name="position">Position of the space.</param>
/// <param name="orientation">Orientation of the space.</param>
/// <param name="locationFlags">XrSpaceLocationFlags for the space.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_SetActionSpace")]
public static extern void SetSpace(ulong actionHandle, Vector3 position, Quaternion orientation, XrSpaceLocationFlags locationFlags);
[DllImport(extLib, EntryPoint = "MockRuntime_RegisterScriptEventCallback")]
private static extern XrResult Internal_RegisterScriptEventCallback(ScriptEventDelegate callback);
[DllImport(extLib, EntryPoint = "MockRuntime_TransitionToState")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool Internal_TransitionToState(XrSessionState state, [MarshalAs(UnmanagedType.I1)] bool forceTransition);
[DllImport(extLib, EntryPoint = "MockRuntime_GetSessionState")]
private static extern XrSessionState Internal_GetSessionState();
/// <summary>
/// Request to exit the runtime session.
/// </summary>
[DllImport(extLib, EntryPoint = "MockRuntime_RequestExitSession")]
public static extern void RequestExitSession();
/// <summary>
/// Force MockRuntime instance loss.
/// </summary>
[DllImport(extLib, EntryPoint = "MockRuntime_CauseInstanceLoss")]
public static extern void CauseInstanceLoss();
/// <summary>
/// Force user presence change.
/// </summary>
/// <param name="hasUserPresent">User present when true.</param>
[DllImport(extLib, EntryPoint = "MockRuntime_CauseUserPresenceChange")]
public static extern void CauseUserPresenceChange([MarshalAs(UnmanagedType.U1)] bool hasUserPresent);
[DllImport(extLib, EntryPoint = "MockRuntime_SetReferenceSpaceBounds")]
internal static extern void SetReferenceSpaceBounds(XrReferenceSpaceType referenceSpace, Vector2 bounds);
[DllImport(extLib, EntryPoint = "MockRuntime_GetEndFrameStats")]
internal static extern void GetEndFrameStats(out int primaryLayerCount, out int secondaryLayerCount);
[DllImport(extLib, EntryPoint = "MockRuntime_ActivateSecondaryView")]
internal static extern void ActivateSecondaryView(XrViewConfigurationType viewConfigurationType, [MarshalAs(UnmanagedType.I1)] bool activate);
[DllImport(extLib, EntryPoint = "MockRuntime_RegisterFunctionCallbacks")]
private static extern void MockRuntime_RegisterFunctionCallbacks(BeforeFunctionDelegate hookBefore, AfterFunctionDelegate hookAfter);
[DllImport(extLib, EntryPoint = "MockRuntime_MetaPerformanceMetrics_SeedCounterOnce_Float")]
internal static extern void MetaPerformanceMetrics_SeedCounterOnce_Float(string xrPathString, float value, uint unit);
[DllImport(extLib, EntryPoint = "MockRuntime_PerformanceSettings_CauseNotification")]
internal static extern void PerformanceSettings_CauseNotification(PerformanceDomain domain, PerformanceSubDomain subDomain, PerformanceNotificationLevel level);
[DllImport(extLib, EntryPoint = "MockRuntime_PerformanceSettings_GetPerformanceLevelHint")]
internal static extern PerformanceLevelHint PerformanceSettings_GetPerformanceLevelHint(PerformanceDomain domain);
#if UNITY_EDITOR
static void UseGenericLoaderAndroid()
{
#if UNITY_2021_3_OR_NEWER
var defines = PlayerSettings.GetScriptingDefineSymbols(NamedBuildTarget.Android);
#else
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
#endif
defines += ";OPENXR_USE_KHRONOS_LOADER";
#if UNITY_2021_3_OR_NEWER
PlayerSettings.SetScriptingDefineSymbols(NamedBuildTarget.Android, defines);
#else
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, defines);
#endif
#if UNITY_2023_1_OR_NEWER
// Use GameActivity if possible so we have test coverage there.
// No JNI on main thread when GameActivity is selected.
PlayerSettings.Android.applicationEntry = AndroidApplicationEntry.GameActivity;
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevel33;
#endif
}
#endif
#if UNITY_ANDROID
[DllImport(extLib, EntryPoint = "MockRuntime_IsAndroidThreadTypeRegistered")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool Internal_IsAndroidThreadTypeRegistered(uint threadType);
[DllImport(extLib, EntryPoint = "MockRuntime_GetRegisteredAndroidThreadsCount")]
private static extern ulong Internal_GetRegisteredAndroidThreadsCount();
#endif
internal static bool IsAndroidThreadTypeRegistered(uint threadType)
{
#if UNITY_ANDROID
return Internal_IsAndroidThreadTypeRegistered(threadType);
#else
return false;
#endif
}
internal static ulong GetRegisteredAndroidThreadsCount()
{
#if UNITY_ANDROID
return Internal_GetRegisteredAndroidThreadsCount();
#else
return 0;
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7de993716e042c6499d0c18eed3a773c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
#if USE_MOCK_FEATURE_SET
using System;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.XR.OpenXR.Features;
namespace UnityEngine.XR.OpenXR.Features.Mock
{
[OpenXRFeatureSet(
FeatureIds = new string[]
{
MockRuntime.featureId,
Interactions.KHRSimpleControllerProfile.featureId,
},
UiName = "Mock Runtime",
Description = "Mock Runtime Feature set support. Enabling this will override any current OpenXR runtime selection.",
FeatureSetId = "com.unity.openxr.featureset.mockruntime",
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Standalone }
)]
public sealed class MockRuntimeFeatureSets {}
}
#endif //UNITY_EDITOR
#endif //USE_MOCK_FEATURE_SET

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dcd9ce9a47c266d469ed6f967ce5be9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
#include "../mock.h"
#define CHECK_EXT() \
if (nullptr == s_ext) \
return XR_ERROR_FUNCTION_UNSUPPORTED;
struct ConformanceAutomation
{
std::map<XrPath, MockInputState> states;
std::map<std::pair<XrPath, XrPath>, bool> activeStates;
MockInputState& GetState(XrPath path, XrActionType actionType)
{
auto it = states.find(path);
if (it != states.end())
return it->second;
MockInputState& state = states[path];
state.type = actionType;
return state;
}
};
static ConformanceAutomation* s_ext = nullptr;
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive)
{
LOG_FUNC();
CHECK_RUNTIME();
CHECK_EXT();
s_ext->activeStates[std::pair<XrPath, XrPath>(interactionProfile, topLevelPath)] = isActive;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state)
{
LOG_FUNC();
CHECK_EXT();
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_BOOLEAN_INPUT).Set(state);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state)
{
LOG_FUNC();
CHECK_EXT();
CHECK_SESSION(session);
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_FLOAT_INPUT).Set(state);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state)
{
LOG_FUNC();
CHECK_EXT();
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_VECTOR2F_INPUT).Set(state);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose)
{
LOG_FUNC();
CHECK_EXT();
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_POSE_INPUT).Set(space, pose);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceVelocityUNITY(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, bool linearValid, XrVector3f linear, bool angularValid, XrVector3f angular)
{
LOG_FUNC();
CHECK_EXT();
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_POSE_INPUT).SetVelocity(linearValid, linear, angularValid, angular);
return XR_SUCCESS;
}
void ConformanceAutomation_Create()
{
// Make sure there is no orphaned extension
ConformanceAutomation_Destroy();
s_ext = new ConformanceAutomation();
}
void ConformanceAutomation_Destroy()
{
delete s_ext;
s_ext = nullptr;
}
XrResult ConformanceAutomation_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
CHECK_EXT();
GET_PROC_ADDRESS(xrSetInputDeviceActiveEXT)
GET_PROC_ADDRESS(xrSetInputDeviceStateBoolEXT)
GET_PROC_ADDRESS(xrSetInputDeviceStateFloatEXT)
GET_PROC_ADDRESS(xrSetInputDeviceStateVector2fEXT)
GET_PROC_ADDRESS(xrSetInputDeviceLocationEXT)
GET_PROC_ADDRESS(xrSetInputDeviceVelocityUNITY)
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
XrResult ConformanceAutomation_GetInputState(MockInputState* state)
{
CHECK_EXT();
auto it = s_ext->states.find(state->path);
if (it == s_ext->states.end())
return XR_ERROR_HANDLE_INVALID;
state->CopyValue(it->second);
return XR_SUCCESS;
}
bool ConformanceAutomation_IsActive(XrPath interactionProfilePath, XrPath userPath, bool defaultValue)
{
if (nullptr == s_ext)
return false;
auto active = s_ext->activeStates.find(std::pair<XrPath, XrPath>(interactionProfilePath, userPath));
if (active == s_ext->activeStates.end())
active = s_ext->activeStates.find(std::pair<XrPath, XrPath>(XR_NULL_PATH, userPath));
return (active != s_ext->activeStates.end()) ? active->second : defaultValue;
}
#undef CHECK_EXT

View File

@@ -0,0 +1,187 @@
#include "../mock.h"
#if defined(XR_USE_GRAPHICS_API_D3D11)
struct MockD3D11
{
ID3D11Device* device = nullptr;
};
static MockD3D11 s_MockD3D11 = {};
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetD3D11GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D11KHR* graphicsRequirements)
{
IDXGIAdapter* pAdapter;
std::vector<IDXGIAdapter*> vAdapters;
IDXGIFactory* pFactory = NULL;
// Create a DXGIFactory object.
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory)))
return XR_ERROR_RUNTIME_FAILURE;
XrResult xrresult = XR_ERROR_RUNTIME_FAILURE;
graphicsRequirements->adapterLuid = {};
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
{
DXGI_ADAPTER_DESC desc = {};
pAdapter->GetDesc(&desc);
graphicsRequirements->adapterLuid = desc.AdapterLuid;
xrresult = XR_SUCCESS;
break;
}
if (pFactory)
pFactory->Release();
return xrresult;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
{
if (nullptr == formatCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
*formatCountOutput = 6;
if (formatCapacityInput == 0)
return XR_SUCCESS;
if (nullptr == formats)
return XR_ERROR_VALIDATION_FAILURE;
if (formatCapacityInput < 6)
return XR_ERROR_SIZE_INSUFFICIENT;
formats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
formats[1] = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
formats[2] = DXGI_FORMAT_R8G8B8A8_UNORM;
formats[3] = DXGI_FORMAT_B8G8R8A8_UNORM;
formats[4] = DXGI_FORMAT_D16_UNORM;
formats[5] = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
return XR_SUCCESS;
}
static XrResult MockD3D11_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
if (nullptr == s_MockD3D11.device)
return XR_ERROR_RUNTIME_FAILURE;
ID3D11Texture2D* texture;
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = createInfo->width;
desc.Height = createInfo->height;
desc.MipLevels = createInfo->mipCount;
desc.ArraySize = createInfo->arraySize;
desc.SampleDesc.Count = createInfo->sampleCount;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
if (createInfo->format == DXGI_FORMAT_D16_UNORM)
desc.Format = DXGI_FORMAT_R16_TYPELESS;
else
desc.Format = DXGI_FORMAT_R32G8X24_TYPELESS;
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
}
else
{
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
}
if (FAILED(s_MockD3D11.device->CreateTexture2D(&desc, NULL, &texture)))
return XR_ERROR_RUNTIME_FAILURE;
*swapchain = (XrSwapchain)texture;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
LOG_FUNC();
MOCK_HOOK_NAMED("xrCreateSwapchain", MockD3D11_xrCreateSwapchain(session, createInfo, swapchain));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrDestroySwapChain(XrSwapchain swapchain)
{
ID3D11Texture2D* texture = (ID3D11Texture2D*)swapchain;
texture->Release();
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
{
LOG_FUNC();
*imageCountOutput = 1;
if (images == nullptr)
return XR_SUCCESS;
if (imageCapacityInput < *imageCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
XrSwapchainImageD3D11KHR* d3d11images = (XrSwapchainImageD3D11KHR*)images;
d3d11images[0].texture = (ID3D11Texture2D*)swapchain;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
{
LOG_FUNC();
*index = 0;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
{
LOG_FUNC();
return XR_SUCCESS;
}
/// <summary>
/// Hook xrCreateSession to get the necessary D3D11 handles
/// </summary>
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
{
s_MockD3D11 = {};
if (createInfo->next != nullptr)
{
XrGraphicsBindingD3D11KHR* bindings = (XrGraphicsBindingD3D11KHR*)createInfo->next;
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_D3D11_KHR)
{
s_MockD3D11.device = bindings->device;
}
}
return xrCreateSession(instance, createInfo, session);
}
XrResult MockD3D11_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
LOG_FUNC();
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockD3D11_xrCreateSession)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockD3D11_xrEnumerateSwapchainFormats)
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockD3D11_xrCreateSwapchainHook)
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockD3D11_xrDestroySwapChain)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockD3D11_xrEnumerateSwapchainImages)
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockD3D11_xrAcquireSwapchainImage)
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockD3D11_xrReleaseSwapchainImage)
GET_PROC_ADDRESS(xrGetD3D11GraphicsRequirementsKHR)
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#endif

View File

@@ -0,0 +1,207 @@
#include "../mock.h"
#if defined(XR_USE_GRAPHICS_API_D3D12)
struct MockD3D12
{
ID3D12Device* device = nullptr;
};
static MockD3D12 s_MockD3D12 = {};
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetD3D12GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D12KHR* graphicsRequirements)
{
IDXGIAdapter* pAdapter;
std::vector<IDXGIAdapter*> vAdapters;
IDXGIFactory* pFactory = NULL;
// Create a DXGIFactory object.
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory)))
return XR_ERROR_RUNTIME_FAILURE;
XrResult xrresult = XR_ERROR_RUNTIME_FAILURE;
graphicsRequirements->adapterLuid = {};
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
{
DXGI_ADAPTER_DESC desc = {};
pAdapter->GetDesc(&desc);
graphicsRequirements->adapterLuid = desc.AdapterLuid;
xrresult = XR_SUCCESS;
break;
}
if (pFactory)
pFactory->Release();
return xrresult;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
{
if (nullptr == formatCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
*formatCountOutput = 6;
if (formatCapacityInput == 0)
return XR_SUCCESS;
if (nullptr == formats)
return XR_ERROR_VALIDATION_FAILURE;
if (formatCapacityInput < 6)
return XR_ERROR_SIZE_INSUFFICIENT;
formats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
formats[1] = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
formats[2] = DXGI_FORMAT_R8G8B8A8_UNORM;
formats[3] = DXGI_FORMAT_B8G8R8A8_UNORM;
formats[4] = DXGI_FORMAT_D16_UNORM;
formats[5] = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
return XR_SUCCESS;
}
static XrResult MockD3D12_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
if (nullptr == s_MockD3D12.device)
{
MOCK_TRACE_DEBUG("Mock device is null");
return XR_ERROR_RUNTIME_FAILURE;
}
D3D12_HEAP_PROPERTIES heapProps{};
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_RESOURCE_DESC desc{};
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Width = createInfo->width;
desc.Height = createInfo->height;
desc.MipLevels = createInfo->mipCount;
desc.DepthOrArraySize = createInfo->arraySize;
desc.SampleDesc.Count = createInfo->sampleCount;
desc.SampleDesc.Quality = 0;
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
if (createInfo->format == DXGI_FORMAT_D16_UNORM)
desc.Format = DXGI_FORMAT_R16_TYPELESS;
else
desc.Format = DXGI_FORMAT_R32G8X24_TYPELESS;
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
}
else
{
desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
}
ID3D12Resource* texture;
const HRESULT result = s_MockD3D12.device->CreateCommittedResource(
&heapProps,
D3D12_HEAP_FLAG_NONE,
&desc,
D3D12_RESOURCE_STATE_RENDER_TARGET,
nullptr,
IID_PPV_ARGS(&texture));
if (FAILED(result))
{
MOCK_TRACE_DEBUG("ID3D12Device::CreateCommittedResource failed, HRESULT: 0x%08x", result);
return XR_ERROR_RUNTIME_FAILURE;
}
else
{
MOCK_TRACE_DEBUG("ID3D12Device::CreateCommittedResource success");
}
*swapchain = (XrSwapchain)texture;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
LOG_FUNC();
MOCK_HOOK_NAMED("xrCreateSwapchain", MockD3D12_xrCreateSwapchain(session, createInfo, swapchain));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrDestroySwapChain(XrSwapchain swapchain)
{
ID3D12Resource* texture = (ID3D12Resource*)swapchain;
texture->Release();
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
{
LOG_FUNC();
*imageCountOutput = 1;
if (images == nullptr)
return XR_SUCCESS;
if (imageCapacityInput < *imageCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
XrSwapchainImageD3D12KHR* d3d12images = (XrSwapchainImageD3D12KHR*)images;
d3d12images[0].texture = (ID3D12Resource*)swapchain;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
{
LOG_FUNC();
*index = 0;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
{
LOG_FUNC();
return XR_SUCCESS;
}
/// <summary>
/// Hook xrCreateSession to get the necessary D3D12 handles
/// </summary>
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
{
s_MockD3D12 = {};
if (createInfo->next != nullptr)
{
XrGraphicsBindingD3D12KHR* bindings = (XrGraphicsBindingD3D12KHR*)createInfo->next;
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_D3D12_KHR)
{
s_MockD3D12.device = bindings->device;
}
}
return xrCreateSession(instance, createInfo, session);
}
XrResult MockD3D12_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
LOG_FUNC();
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockD3D12_xrCreateSession)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockD3D12_xrEnumerateSwapchainFormats)
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockD3D12_xrCreateSwapchainHook)
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockD3D12_xrDestroySwapChain)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockD3D12_xrEnumerateSwapchainImages)
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockD3D12_xrAcquireSwapchainImage)
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockD3D12_xrReleaseSwapchainImage)
GET_PROC_ADDRESS(xrGetD3D12GraphicsRequirementsKHR)
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#endif

View File

@@ -0,0 +1,82 @@
#include "mock_khr_android_thread_settings.h"
#ifdef XR_USE_PLATFORM_ANDROID
#define CHECK_EXT_INIT() \
if (nullptr == MockAndroidThreadSettings::Instance()) \
return XR_ERROR_FUNCTION_UNSUPPORTED;
std::unique_ptr<MockAndroidThreadSettings> MockAndroidThreadSettings::s_Instance;
MockAndroidThreadSettings* MockAndroidThreadSettings::Instance()
{
return s_Instance.get();
}
void MockAndroidThreadSettings::Init(MockRuntime& runtime)
{
s_Instance.reset(new MockAndroidThreadSettings(runtime));
}
void MockAndroidThreadSettings::Deinit()
{
s_Instance.reset();
}
MockAndroidThreadSettings::MockAndroidThreadSettings(MockRuntime& runtime)
: m_Runtime{runtime}
{
}
XrResult MockAndroidThreadSettings::SetAndroidApplicationThread(XrAndroidThreadTypeKHR threadType, uint32_t threadId)
{
m_AssignedThreadTypes[threadId] = threadType;
return XR_SUCCESS;
}
bool MockAndroidThreadSettings::IsAndroidThreadTypeRegistered(XrAndroidThreadTypeKHR threadType) const
{
for (auto i = m_AssignedThreadTypes.cbegin(); i != m_AssignedThreadTypes.cend(); ++i)
{
if (i->second == threadType)
{
return true;
}
}
return false;
}
uint32_t MockAndroidThreadSettings::GetRegisteredAndroidThreadsCount() const
{
return m_AssignedThreadTypes.size();
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrSetAndroidApplicationThreadKHR(
XrSession session,
XrAndroidThreadTypeKHR threadType,
uint32_t threadId)
{
LOG_FUNC();
CHECK_SESSION(session);
CHECK_EXT_INIT();
MOCK_HOOK_BEFORE();
const XrResult result =
MockAndroidThreadSettings::Instance()->SetAndroidApplicationThread(
threadType,
threadId);
MOCK_HOOK_AFTER(result);
return result;
}
XrResult MockAndroidThreadSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
GET_PROC_ADDRESS(xrSetAndroidApplicationThreadKHR)
return XR_ERROR_FEATURE_UNSUPPORTED;
}
#undef CHECK_EXT_INIT
#endif // XR_USE_PLATFORM_ANDROID

View File

@@ -0,0 +1,29 @@
#pragma once
#include "../mock.h"
#include <map>
#include <memory>
#ifdef XR_USE_PLATFORM_ANDROID
class MockAndroidThreadSettings
{
public:
static MockAndroidThreadSettings* Instance();
static void Init(MockRuntime& runtime);
static void Deinit();
MockAndroidThreadSettings(MockRuntime& runtime);
XrResult SetAndroidApplicationThread(XrAndroidThreadTypeKHR threadType, uint32_t threadId);
bool IsAndroidThreadTypeRegistered(XrAndroidThreadTypeKHR threadType) const;
uint32_t GetRegisteredAndroidThreadsCount() const;
private:
static std::unique_ptr<MockAndroidThreadSettings> s_Instance;
MockRuntime& m_Runtime;
std::map<uint32_t, XrAndroidThreadTypeKHR> m_AssignedThreadTypes{};
};
XrResult MockAndroidThreadSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
#endif

View File

@@ -0,0 +1,304 @@
#include "mock_meta_performance_metrics.h"
#include "../mock.h"
#include <sstream>
#define CHECK_EXT() \
if (nullptr == MockMetaPerformanceMetrics::Instance()) \
return XR_ERROR_FUNCTION_UNSUPPORTED;
// storage for static
std::unique_ptr<MockMetaPerformanceMetrics> MockMetaPerformanceMetrics::s_ext;
enum class MockMetaPerformanceMetrics::InternalPaths : int
{
Invalid = 0,
AppCPUFrametime,
AppGPUFrametime,
AppMotionToPhotonLatency,
CompositorCPUFrametime,
CompositorGPUFrametime,
CompositorDroppedFrameCount,
CompositorSpacewarpMode,
DeviceCPUUtilizationAvg,
DeviceCPUUtilizationWorst,
DeviceGPUUtilization,
};
namespace
{
constexpr char kAppCPUFrametimeStr[] = "/perfmetrics_meta/app/cpu_frametime";
constexpr char kAppGPUFrametimeStr[] = "/perfmetrics_meta/app/gpu_frametime";
constexpr char kAppMotionToPhotonLatencyStr[] = "/perfmetrics_meta/app/motion_to_photon_latency";
constexpr char kCompositorCPUFrametimeStr[] = "/perfmetrics_meta/compositor/cpu_frametime";
constexpr char kCompositorGPUFrametimeStr[] = "/perfmetrics_meta/compositor/gpu_frametime";
constexpr char kCompositorDroppedFrameCountStr[] = "/perfmetrics_meta/compositor/dropped_frame_count";
constexpr char kCompositorSpacewarpModeStr[] = "/perfmetrics_meta/compositor/spacewarp_mode";
constexpr char kDeviceCPUUtilizationAvgStr[] = "/perfmetrics_meta/device/cpu_utilization_average";
constexpr char kDeviceCPUUtilizationWorstStr[] = "/perfmetrics_meta/device/cpu_utilization_worst";
constexpr char kDeviceGPUUtilizationStr[] = "/perfmetrics_meta/device/gpu_utilization";
} // namespace
MockMetaPerformanceMetrics::InternalPaths MockMetaPerformanceMetrics::InternalPathFromString(
const std::string& s)
{
if (s == kAppCPUFrametimeStr)
return InternalPaths::AppCPUFrametime;
if (s == kAppGPUFrametimeStr)
return InternalPaths::AppGPUFrametime;
if (s == kAppMotionToPhotonLatencyStr)
return InternalPaths::AppMotionToPhotonLatency;
if (s == kCompositorCPUFrametimeStr)
return InternalPaths::CompositorCPUFrametime;
if (s == kCompositorGPUFrametimeStr)
return InternalPaths::CompositorGPUFrametime;
if (s == kCompositorDroppedFrameCountStr)
return InternalPaths::CompositorDroppedFrameCount;
if (s == kCompositorSpacewarpModeStr)
return InternalPaths::CompositorSpacewarpMode;
if (s == kDeviceCPUUtilizationAvgStr)
return InternalPaths::DeviceCPUUtilizationAvg;
if (s == kDeviceCPUUtilizationWorstStr)
return InternalPaths::DeviceCPUUtilizationWorst;
if (s == kDeviceGPUUtilizationStr)
return InternalPaths::DeviceGPUUtilization;
return InternalPaths::Invalid;
}
MockMetaPerformanceMetrics::MockMetaPerformanceMetrics(MockRuntime& runtime, const int numMockCPUs)
: m_NumMockCPUs{numMockCPUs}
, m_Runtime{runtime}
{
static constexpr const char* k_ListPaths[] = {
kAppCPUFrametimeStr,
kAppGPUFrametimeStr,
kAppMotionToPhotonLatencyStr,
kCompositorCPUFrametimeStr,
kCompositorGPUFrametimeStr,
kCompositorDroppedFrameCountStr,
kCompositorSpacewarpModeStr,
kDeviceCPUUtilizationAvgStr,
kDeviceCPUUtilizationWorstStr,
kDeviceGPUUtilizationStr,
};
for (const char* const pathString : k_ListPaths)
{
const XrPath path = runtime.StringToPath(pathString);
m_Paths[path] = InternalPathFromString(pathString);
}
for (int i = 0; i < m_NumMockCPUs; i++)
{
std::stringstream ss{"/perfmetrics_meta/device/cpu"};
ss << i << "_utilization";
std::string pathString = ss.str();
const XrPath path = runtime.StringToPath(pathString.c_str());
m_Paths[path] = InternalPathFromString(pathString);
}
}
void MockMetaPerformanceMetrics::Init(MockRuntime& runtime, const int numMockCPUs)
{
s_ext.reset(new MockMetaPerformanceMetrics(runtime, numMockCPUs));
}
void MockMetaPerformanceMetrics::Deinit()
{
s_ext.reset();
}
MockMetaPerformanceMetrics* MockMetaPerformanceMetrics::Instance()
{
return s_ext.get();
}
XrResult MockMetaPerformanceMetrics::EnumeratePaths(
XrInstance instance,
uint32_t counterPathCapacityInput,
uint32_t* counterPathCountOutput,
XrPath* counterPaths)
{
*counterPathCountOutput = static_cast<uint32_t>(m_Paths.size());
if (counterPathCapacityInput >= *counterPathCountOutput)
{
int i = 0;
for (const auto kv : m_Paths)
{
counterPaths[i] = kv.first;
i++;
}
}
return XR_SUCCESS;
}
XrResult MockMetaPerformanceMetrics::SetState(XrSession session, const XrPerformanceMetricsStateMETA* state)
{
if (!state || state->type != XR_TYPE_PERFORMANCE_METRICS_STATE_META)
{
return XR_ERROR_VALIDATION_FAILURE;
}
m_Enabled = state->enabled == XR_TRUE;
return XR_SUCCESS;
}
XrResult MockMetaPerformanceMetrics::GetState(XrSession session, XrPerformanceMetricsStateMETA* state)
{
if (!state || state->type != XR_TYPE_PERFORMANCE_METRICS_STATE_META)
{
return XR_ERROR_VALIDATION_FAILURE;
}
state->enabled = m_Enabled ? XR_TRUE : XR_FALSE;
return XR_SUCCESS;
}
XrResult MockMetaPerformanceMetrics::QueryCounter(
XrSession session,
XrPath counterPath,
XrPerformanceMetricsCounterMETA* counter)
{
if (!m_Enabled || !counter || counter->type != XR_TYPE_PERFORMANCE_METRICS_COUNTER_META)
{
// disabled state return value confirmed by Xiang Wei @ Meta.
return XR_ERROR_VALIDATION_FAILURE;
}
std::list<MockResult>& values = m_SeededResults[m_Paths[counterPath]];
if (values.empty())
{
if (!m_NoResultsSeededWarningShown)
{
m_NoResultsSeededWarningShown = true;
MOCK_TRACE_DEBUG("No results were seeded for the requested stat. If you aren't testing stats, ignore this warning.");
}
*counter = m_DefaultResult.value;
return m_DefaultResult.rv;
}
// FIFO, fill in the counter struct and return the seeded return value.
*counter = values.front().value;
XrResult rv = values.front().rv;
values.pop_front();
return rv;
}
void MockMetaPerformanceMetrics::SeedCounterOnce(const std::string& counterPathString, MockResult result)
{
const XrPath path = m_Runtime.StringToPath(counterPathString.c_str());
if (path == XR_NULL_PATH)
{
// providing an invalid path during testing shouldn't happen, kill and warn our dev
// if you want to test whether a path exists, use the runtime functions themselves.
MOCK_TRACE_ERROR("Could not find path %s", counterPathString.c_str());
return;
}
if (result.value.type != XR_TYPE_PERFORMANCE_METRICS_COUNTER_META)
{
MOCK_TRACE_ERROR(
"Invalid or no type supplied for XrPerformanceMetricsCounterMETA. Type MUST be"
" XR_TYPE_PERFORMANCE_METRICS_COUNTER_META.");
return;
}
if (result.value.next != nullptr)
{
MOCK_TRACE_ERROR(
"This structure does not currently support chaining (`next` should be `nullptr`).");
return;
}
std::list<MockResult>& values = m_SeededResults[m_Paths[path]];
values.push_back(result);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrEnumeratePerformanceMetricsCounterPathsMETA(
XrInstance instance,
uint32_t counterPathCapacityInput,
uint32_t* counterPathCountOutput,
XrPath* counterPaths)
{
LOG_FUNC();
CHECK_RUNTIME();
CHECK_INSTANCE(instance);
CHECK_EXT();
MOCK_HOOK_BEFORE();
const XrResult result =
MockMetaPerformanceMetrics::Instance()->EnumeratePaths(
instance,
counterPathCapacityInput,
counterPathCountOutput,
counterPaths);
MOCK_HOOK_AFTER(result);
return result;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrSetPerformanceMetricsStateMETA(
XrSession session,
const XrPerformanceMetricsStateMETA* state)
{
LOG_FUNC();
CHECK_SESSION(session);
CHECK_EXT();
MOCK_HOOK_BEFORE();
const XrResult result = MockMetaPerformanceMetrics::Instance()->SetState(session, state);
MOCK_HOOK_AFTER(result);
return result;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrGetPerformanceMetricsStateMETA(
XrSession session,
XrPerformanceMetricsStateMETA* state)
{
LOG_FUNC();
CHECK_SESSION(session);
CHECK_EXT();
MOCK_HOOK_BEFORE();
const XrResult result = MockMetaPerformanceMetrics::Instance()->GetState(session, state);
MOCK_HOOK_AFTER(result);
return result;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrQueryPerformanceMetricsCounterMETA(
XrSession session,
XrPath counterPath,
XrPerformanceMetricsCounterMETA* counter)
{
LOG_FUNC();
CHECK_SESSION(session);
CHECK_EXT();
MOCK_HOOK_BEFORE();
const XrResult result =
MockMetaPerformanceMetrics::Instance()->QueryCounter(
session,
counterPath,
counter);
MOCK_HOOK_AFTER(result);
return result;
}
XrResult MockMetaPerformanceMetrics_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
GET_PROC_ADDRESS(xrEnumeratePerformanceMetricsCounterPathsMETA)
GET_PROC_ADDRESS(xrSetPerformanceMetricsStateMETA)
GET_PROC_ADDRESS(xrGetPerformanceMetricsStateMETA)
GET_PROC_ADDRESS(xrQueryPerformanceMetricsCounterMETA)
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#undef CHECK_EXT

View File

@@ -0,0 +1,73 @@
// Mock extension for XR_META_performance_metrics extension
// https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_META_performance_metrics
#pragma once
#include "openxr/openxr.h"
#include <list>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
class MockRuntime;
class MockMetaPerformanceMetrics
{
public:
enum class InternalPaths : int;
struct MockResult
{
XrResult rv;
XrPerformanceMetricsCounterMETA value;
};
static void Init(MockRuntime& runtime, const int numMockCPUs);
static void Deinit();
static MockMetaPerformanceMetrics* Instance();
static InternalPaths InternalPathFromString(const std::string& s);
XrResult EnumeratePaths(
XrInstance instance,
uint32_t counterPathCapacityInput,
uint32_t* counterPathCountOutput,
XrPath* counterPaths);
XrResult SetState(XrSession session, const XrPerformanceMetricsStateMETA* state);
XrResult GetState(XrSession session, XrPerformanceMetricsStateMETA* state);
XrResult QueryCounter(
XrSession session,
XrPath counterPath,
XrPerformanceMetricsCounterMETA* counter);
void SeedCounterOnce(const std::string& counterPath, MockResult result);
private:
MockMetaPerformanceMetrics(MockRuntime& runtime, const int numMockCPUs);
static std::unique_ptr<MockMetaPerformanceMetrics> s_ext;
MockRuntime& m_Runtime;
const int m_NumMockCPUs;
// we use an ordered set just to keep things consistent for enumeration
std::map<XrPath, InternalPaths> m_Paths;
bool m_Enabled;
bool m_NoResultsSeededWarningShown;
std::map<InternalPaths, std::list<MockResult>> m_SeededResults;
MockResult m_DefaultResult{
XR_SUCCESS,
{
XR_TYPE_PERFORMANCE_METRICS_COUNTER_META,
nullptr,
XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META,
XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META,
0,
0.f,
}};
};
XrResult MockMetaPerformanceMetrics_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);

View File

@@ -0,0 +1,21 @@
#include "../mock.h"
XrResult MockRuntime::MSFTFirstPersonObserver_Init()
{
MockViewConfiguration firstPersonConfig = {};
firstPersonConfig.primary = false;
firstPersonConfig.enabled = false;
firstPersonConfig.active = false;
firstPersonConfig.stateFlags = XR_VIEW_STATE_ORIENTATION_TRACKED_BIT |
XR_VIEW_STATE_ORIENTATION_VALID_BIT |
XR_VIEW_STATE_POSITION_TRACKED_BIT |
XR_VIEW_STATE_POSITION_VALID_BIT;
firstPersonConfig.views = {
{viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO].views[0].configuration,
{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{-0.995535672f, 0.995566666f, 0.954059243f, -0.954661012f}}};
viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT] = firstPersonConfig;
return XR_SUCCESS;
}

View File

@@ -0,0 +1,114 @@
#include "../mock.h"
XrResult MockRuntime::MSFTSecondaryViewConfiguration_BeginSession(const XrSessionBeginInfo* beginInfo)
{
// Check for secondary view configuration
const XrSecondaryViewConfigurationSessionBeginInfoMSFT* secondaryViewConfiguration =
FindNextPointerType<XrSecondaryViewConfigurationSessionBeginInfoMSFT>(beginInfo, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT);
if (nullptr == secondaryViewConfiguration)
return XR_SUCCESS;
if (secondaryViewConfiguration->viewConfigurationCount == 0)
return XR_ERROR_VALIDATION_FAILURE;
if (secondaryViewConfiguration->enabledViewConfigurationTypes == nullptr)
return XR_ERROR_VALIDATION_FAILURE;
secondaryViewConfigurationStates.reserve(secondaryViewConfiguration->viewConfigurationCount);
for (uint32_t i = 0; i < secondaryViewConfiguration->viewConfigurationCount; i++)
{
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(secondaryViewConfiguration->enabledViewConfigurationTypes[i]);
if (nullptr == viewConfiguration)
return XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED;
if (viewConfiguration->primary || viewConfiguration->enabled)
return XR_ERROR_VALIDATION_FAILURE;
viewConfiguration->enabled = true;
XrSecondaryViewConfigurationStateMSFT viewState = {XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT};
viewState.viewConfigurationType = secondaryViewConfiguration->enabledViewConfigurationTypes[i];
viewState.active = viewConfiguration->active;
secondaryViewConfigurationStates.push_back(viewState);
}
return XR_SUCCESS;
}
XrResult MockRuntime::MSFTSecondaryViewConfiguration_WaitFrame(const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState)
{
// Check for secondary view configuration
XrSecondaryViewConfigurationFrameStateMSFT* secondaryFrameState =
FindNextPointerType<XrSecondaryViewConfigurationFrameStateMSFT>(frameState, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT);
if (secondaryFrameState == nullptr)
return XR_SUCCESS;
if (secondaryFrameState->viewConfigurationCount == 0 || secondaryFrameState->viewConfigurationStates == nullptr)
return XR_ERROR_VALIDATION_FAILURE;
if (secondaryFrameState->viewConfigurationCount != (uint32_t)secondaryViewConfigurationStates.size())
return XR_ERROR_VALIDATION_FAILURE;
for (auto& viewConfiguration : secondaryViewConfigurationStates)
{
if (viewConfiguration.viewConfigurationType != 0)
{
viewConfiguration.active = GetMockViewConfiguration(viewConfiguration.viewConfigurationType)->active;
}
}
memcpy(secondaryFrameState->viewConfigurationStates, secondaryViewConfigurationStates.data(), secondaryViewConfigurationStates.size() * sizeof(XrSecondaryViewConfigurationStateMSFT));
return XR_SUCCESS;
}
XrResult MockRuntime::MSFTSecondaryViewConfiguration_EndFrame(const XrFrameEndInfo* frameEndInfo)
{
const XrSecondaryViewConfigurationFrameEndInfoMSFT* secondaryFrameEndInfo =
FindNextPointerType<XrSecondaryViewConfigurationFrameEndInfoMSFT>(frameEndInfo, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT);
if (secondaryFrameEndInfo == nullptr)
return XR_SUCCESS;
if (secondaryFrameEndInfo->viewConfigurationCount == 0 || secondaryFrameEndInfo->viewConfigurationLayersInfo == nullptr)
return XR_ERROR_VALIDATION_FAILURE;
for (uint32_t i = 0; i < secondaryFrameEndInfo->viewConfigurationCount; i++)
{
auto& info = secondaryFrameEndInfo->viewConfigurationLayersInfo[0];
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(info.viewConfigurationType);
if (viewConfiguration->primary)
return XR_ERROR_LAYER_INVALID;
if (!viewConfiguration->enabled)
return XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT;
if (!viewConfiguration->active)
continue;
secondaryLayersRendered += info.layerCount;
}
return XR_SUCCESS;
}
XrResult MockRuntime::ActivateSecondaryView(XrViewConfigurationType viewConfigurationType, bool active)
{
if (viewConfigurationType == 0)
{
// emulating a bug we saw with microsoft runtime
secondaryViewConfigurationStates.clear();
secondaryViewConfigurationStates.push_back({XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT});
}
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(viewConfigurationType);
if (nullptr == viewConfiguration || (IsSessionRunning() && !viewConfiguration->enabled))
return XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT;
if (viewConfiguration->primary)
return XR_ERROR_VALIDATION_FAILURE;
viewConfiguration->active = active;
return XR_SUCCESS;
}

View File

@@ -0,0 +1,21 @@
#include "../mock.h"
XrResult MockRuntime::MSFTThirdPersonObserver_Init()
{
MockViewConfiguration thirdPersonConfig = {};
thirdPersonConfig.primary = false;
thirdPersonConfig.enabled = false;
thirdPersonConfig.active = false;
thirdPersonConfig.stateFlags = XR_VIEW_STATE_ORIENTATION_TRACKED_BIT |
XR_VIEW_STATE_ORIENTATION_VALID_BIT |
XR_VIEW_STATE_POSITION_TRACKED_BIT |
XR_VIEW_STATE_POSITION_VALID_BIT;
thirdPersonConfig.views = {
{viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO].views[0].configuration,
{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{-0.995535672f, 0.995566666f, 0.954059243f, -0.954661012f}}};
viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_THIRD_PERSON_OBSERVER_MSFT] = thirdPersonConfig;
return XR_SUCCESS;
}

View File

@@ -0,0 +1,97 @@
#include "mock_performance_settings.h"
#define CHECK_PERF_SETTINGS_EXT() \
if (nullptr == MockPerformanceSettings::Instance()) \
return XR_ERROR_FUNCTION_UNSUPPORTED;
std::unique_ptr<MockPerformanceSettings> MockPerformanceSettings::s_ext;
void MockPerformanceSettings::Init(MockRuntime& runtime)
{
s_ext.reset(new MockPerformanceSettings(runtime));
}
void MockPerformanceSettings::Deinit()
{
s_ext.reset();
}
MockPerformanceSettings* MockPerformanceSettings::Instance()
{
return s_ext.get();
}
MockPerformanceSettings::MockPerformanceSettings(MockRuntime& runtime)
: m_Runtime(runtime)
{
}
XrResult MockPerformanceSettings::SetPerformanceLevel(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level)
{
if (domain != XR_PERF_SETTINGS_DOMAIN_CPU_EXT &&
domain != XR_PERF_SETTINGS_DOMAIN_GPU_EXT)
{
return XR_ERROR_VALIDATION_FAILURE;
}
if (level != XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT &&
level != XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT &&
level != XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT &&
level != XR_PERF_SETTINGS_LEVEL_BOOST_EXT)
{
return XR_ERROR_VALIDATION_FAILURE;
}
m_PerformanceLevelHints[domain] = level;
return XR_SUCCESS;
}
XrPerfSettingsLevelEXT MockPerformanceSettings::GetPerformanceLevelHint(XrPerfSettingsDomainEXT domain)
{
if (m_PerformanceLevelHints.find(domain) != m_PerformanceLevelHints.end())
{
return m_PerformanceLevelHints[domain];
}
return XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT; // Default value per spec
}
XrPerfSettingsNotificationLevelEXT MockPerformanceSettings::GetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain)
{
auto pair = std::make_pair(domain, subdomain);
return m_notificationLevel[pair];
}
void MockPerformanceSettings::SetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT nextLevel)
{
auto pair = std::make_pair(domain, subdomain);
m_notificationLevel[pair] = nextLevel;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
xrPerfSettingsSetPerformanceLevelEXT(
XrSession session,
XrPerfSettingsDomainEXT domain,
XrPerfSettingsLevelEXT level)
{
LOG_FUNC();
CHECK_SESSION(session);
CHECK_PERF_SETTINGS_EXT();
MOCK_HOOK_BEFORE();
const XrResult result =
MockPerformanceSettings::Instance()->SetPerformanceLevel(session, domain, level);
MOCK_HOOK_AFTER(result);
return result;
}
XrResult MockPerformanceSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
GET_PROC_ADDRESS(xrPerfSettingsSetPerformanceLevelEXT);
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#undef CHECK_PERF_SETTINGS_EXT

View File

@@ -0,0 +1,37 @@
#pragma once
#include <map>
#include <memory>
#include "../mock.h"
#include "IUnityInterface.h"
#include "openxr/openxr.h"
#include "openxr/openxr_platform_defines.h"
class MockRuntime;
class MockPerformanceSettings
{
public:
static void Init(MockRuntime& runtime);
static void Deinit();
static MockPerformanceSettings* Instance();
XrResult SetPerformanceLevel(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level);
XrPerfSettingsLevelEXT GetPerformanceLevelHint(XrPerfSettingsDomainEXT domain);
XrPerfSettingsNotificationLevelEXT GetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain);
void SetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT nextLevel);
private:
static std::unique_ptr<MockPerformanceSettings> s_ext;
MockRuntime& m_Runtime;
std::map<XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT> m_PerformanceLevelHints;
std::map<std::pair<XrPerfSettingsDomainEXT, XrPerfSettingsSubDomainEXT>, XrPerfSettingsNotificationLevelEXT> m_notificationLevel;
MockPerformanceSettings(MockRuntime& runtime);
};
XrResult MockPerformanceSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);

View File

@@ -0,0 +1,317 @@
#include "../mock.h"
#if defined(XR_USE_GRAPHICS_API_VULKAN)
struct MockVulkan
{
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice phsyicalDevice = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE;
VkQueue queue = VK_NULL_HANDLE;
VkPhysicalDeviceMemoryProperties memoryProperties = {};
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = nullptr;
PFN_vkAllocateMemory vkAllocateMemory = nullptr;
PFN_vkCreateImage vkCreateImage = nullptr;
PFN_vkCreateDevice vkCreateDevice = nullptr;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = nullptr;
PFN_vkBindImageMemory vkBindImageMemory = nullptr;
PFN_vkDestroyImage vkDestroyImage = nullptr;
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = nullptr;
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = nullptr;
};
static MockVulkan s_MockVulkan = {};
static bool GetVulkanMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties, uint32_t* index)
{
for (uint32_t i = 0; i < s_MockVulkan.memoryProperties.memoryTypeCount; i++, typeBits >>= 1)
{
// Only consider memory types included in the typeBits mask
if ((typeBits & 1) == 0)
continue;
// If all requested properties are a match then return this memory type
if ((s_MockVulkan.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
*index = i;
return true;
}
}
return false;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
{
if (nullptr == bufferCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
*bufferCountOutput = 0;
if (bufferCapacityInput > 0 && buffer == nullptr)
return XR_ERROR_VALIDATION_FAILURE;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
{
if (nullptr == bufferCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
*bufferCountOutput = 0;
if (bufferCapacityInput > 0 && buffer == nullptr)
return XR_ERROR_VALIDATION_FAILURE;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice)
{
*vkPhysicalDevice = s_MockVulkan.phsyicalDevice;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateVulkanInstanceKHR(
XrInstance instance,
const XrVulkanInstanceCreateInfoKHR* createInfo,
VkInstance* vulkanInstance,
VkResult* vulkanResult)
{
s_MockVulkan = {};
s_MockVulkan.vkGetInstanceProcAddr = createInfo->pfnGetInstanceProcAddr;
if (s_MockVulkan.vkGetInstanceProcAddr == nullptr)
return XR_ERROR_RUNTIME_FAILURE;
PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)s_MockVulkan.vkGetInstanceProcAddr(nullptr, "vkCreateInstance");
if (nullptr == vkCreateInstance)
return XR_ERROR_RUNTIME_FAILURE;
if (VK_SUCCESS != vkCreateInstance(createInfo->vulkanCreateInfo, createInfo->vulkanAllocator, vulkanInstance))
return XR_ERROR_RUNTIME_FAILURE;
#define VK_GET_PROC_ADDR(func) s_MockVulkan.func = (PFN_##func)s_MockVulkan.vkGetInstanceProcAddr(*vulkanInstance, #func);
VK_GET_PROC_ADDR(vkCreateImage)
VK_GET_PROC_ADDR(vkCreateDevice)
VK_GET_PROC_ADDR(vkDestroyImage)
VK_GET_PROC_ADDR(vkGetPhysicalDeviceMemoryProperties)
VK_GET_PROC_ADDR(vkGetImageMemoryRequirements)
VK_GET_PROC_ADDR(vkAllocateMemory)
VK_GET_PROC_ADDR(vkBindImageMemory)
VK_GET_PROC_ADDR(vkEnumeratePhysicalDevices)
#undef VK_GET_PROC_ADDR
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateVulkanDeviceKHR(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* device, VkResult* result)
{
*result = s_MockVulkan.vkCreateDevice(createInfo->vulkanPhysicalDevice, createInfo->vulkanCreateInfo, createInfo->vulkanAllocator, device);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsRequirements2KHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements)
{
graphicsRequirements->minApiVersionSupported = VK_MAKE_VERSION(0, 0, 0);
graphicsRequirements->maxApiVersionSupported = VK_MAKE_VERSION(255, 255, 255);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsDevice2KHR(
XrInstance instance,
const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
VkPhysicalDevice* vulkanPhysicalDevice)
{
if (nullptr == s_MockVulkan.vkEnumeratePhysicalDevices)
{
*vulkanPhysicalDevice = nullptr;
return XR_SUCCESS;
}
uint32_t physicalDeviceCount = 0;
s_MockVulkan.vkEnumeratePhysicalDevices(getInfo->vulkanInstance, &physicalDeviceCount, nullptr);
if (physicalDeviceCount == 0)
return XR_ERROR_RUNTIME_FAILURE;
std::vector<VkPhysicalDevice> physicalDevices;
physicalDevices.resize(physicalDeviceCount);
s_MockVulkan.vkEnumeratePhysicalDevices(getInfo->vulkanInstance, &physicalDeviceCount, physicalDevices.data());
if (physicalDeviceCount != (uint32_t)physicalDevices.size())
return XR_ERROR_RUNTIME_FAILURE;
*vulkanPhysicalDevice = physicalDevices[0];
return XR_SUCCESS;
}
/// <summary>
/// Hook xrCreateSession to get the necessary vulkan handles
/// </summary>
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
{
if (createInfo->next != nullptr)
{
XrGraphicsBindingVulkanKHR* bindings = (XrGraphicsBindingVulkanKHR*)createInfo->next;
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR)
{
s_MockVulkan.device = bindings->device;
s_MockVulkan.instance = bindings->instance;
s_MockVulkan.phsyicalDevice = bindings->physicalDevice;
if (s_MockVulkan.vkGetPhysicalDeviceMemoryProperties == nullptr)
return XR_ERROR_RUNTIME_FAILURE;
s_MockVulkan.vkGetPhysicalDeviceMemoryProperties(s_MockVulkan.phsyicalDevice, &s_MockVulkan.memoryProperties);
}
}
return xrCreateSession(instance, createInfo, session);
}
static VkImage CreateSwapchainImage(const XrSwapchainCreateInfo* createInfo)
{
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = (VkFormat)createInfo->format;
imageCreateInfo.mipLevels = createInfo->mipCount;
imageCreateInfo.arrayLayers = createInfo->arraySize;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.extent.width = createInfo->width;
imageCreateInfo.extent.height = createInfo->height;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.usage = 0;
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT)
imageCreateInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
imageCreateInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
VkImage vkimage;
s_MockVulkan.vkCreateImage(s_MockVulkan.device, &imageCreateInfo, nullptr, &vkimage);
// Allocate memory to back the destination image
VkMemoryRequirements memRequirements;
s_MockVulkan.vkGetImageMemoryRequirements(s_MockVulkan.device, vkimage, &memRequirements);
VkDeviceMemory imageMemory;
VkMemoryAllocateInfo memAllocInfo = {};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memRequirements.size;
if (!GetVulkanMemoryTypeIndex(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex))
return VK_NULL_HANDLE;
s_MockVulkan.vkAllocateMemory(s_MockVulkan.device, &memAllocInfo, nullptr, &imageMemory);
s_MockVulkan.vkBindImageMemory(s_MockVulkan.device, vkimage, imageMemory, 0);
return vkimage;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
LOG_FUNC();
*swapchain = (XrSwapchain)CreateSwapchainImage(createInfo);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
LOG_FUNC();
MOCK_HOOK_NAMED("xrCreateSwapchain", MockVulkan_xrCreateSwapchain(session, createInfo, swapchain));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrDestroySwapChain(XrSwapchain swapchain)
{
s_MockVulkan.vkDestroyImage(s_MockVulkan.device, (VkImage)swapchain, nullptr);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
{
LOG_FUNC();
*index = 0;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
{
LOG_FUNC();
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
{
if (nullptr == formatCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
*formatCountOutput = 3;
if (formatCapacityInput == 0)
return XR_SUCCESS;
if (nullptr == formats)
return XR_ERROR_VALIDATION_FAILURE;
if (formatCapacityInput < 3)
return XR_ERROR_SIZE_INSUFFICIENT;
formats[0] = VK_FORMAT_R8G8B8A8_SRGB;
formats[1] = VK_FORMAT_D16_UNORM;
formats[2] = VK_FORMAT_D24_UNORM_S8_UINT;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
{
LOG_FUNC();
*imageCountOutput = 1;
if (images == nullptr)
return XR_SUCCESS;
if (imageCapacityInput < *imageCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
XrSwapchainImageVulkanKHR* vkimages = (XrSwapchainImageVulkanKHR*)images;
vkimages[0].image = (VkImage)swapchain;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEndFrame(XrSession session, const XrFrameEndInfo* frameEndInfo);
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEndFrame(XrSession session, const XrFrameEndInfo* frameEndInfo)
{
return xrEndFrame(session, frameEndInfo);
}
XrResult MockVulkan_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
{
LOG_FUNC();
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockVulkan_xrCreateSession)
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockVulkan_xrCreateSwapchainHook)
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockVulkan_xrDestroySwapChain)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockVulkan_xrEnumerateSwapchainFormats)
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockVulkan_xrEnumerateSwapchainImages)
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockVulkan_xrAcquireSwapchainImage)
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockVulkan_xrReleaseSwapchainImage)
GET_PROC_ADDRESS_REMAP(xrEndFrame, MockVulkan_xrEndFrame)
GET_PROC_ADDRESS(xrCreateVulkanInstanceKHR)
GET_PROC_ADDRESS(xrGetVulkanGraphicsRequirements2KHR)
GET_PROC_ADDRESS(xrGetVulkanGraphicsDevice2KHR)
GET_PROC_ADDRESS(xrCreateVulkanDeviceKHR)
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#endif // XR_USE_GRAPHICS_API_VULKAN

View File

@@ -0,0 +1,205 @@
#pragma once
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // !WIN32_LEAN_AND_MEAN
#include <d3d11.h>
#include <d3d12.h>
#include <windows.h>
#endif
#ifdef XR_USE_PLATFORM_ANDROID
#include <jni.h>
#include <sstream>
#include <string.h>
#include <string>
#include <sys/system_properties.h>
namespace std
{
template <typename T>
std::string to_string(T value)
{
std::ostringstream os;
os << value;
return os.str();
}
} // namespace std
#endif
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#endif
#include <vulkan/vulkan.h>
struct IUnityXRTrace;
extern IUnityXRTrace* s_Trace;
#define DEBUG_TRACE 1
#define MOCK_TRACE(TYPE, STRING, ...) \
if (s_Trace != nullptr) \
s_Trace->Trace(TYPE, "[Mock] " STRING "\n", ##__VA_ARGS__)
#define MOCK_TRACE_LOG(STRING, ...) MOCK_TRACE(kXRLogTypeLog, STRING, ##__VA_ARGS__)
#define MOCK_TRACE_ERROR(STRING, ...) MOCK_TRACE(kXRLogTypeError, STRING, ##__VA_ARGS__)
#if DEBUG_TRACE
#define MOCK_TRACE_DEBUG(STRING, ...) MOCK_TRACE(kXRLogTypeDebug, STRING, ##__VA_ARGS__)
#else
#define MOCK_TRACE_DEBUG(STRING, ...)
#endif
#define XR_NO_PROTOTYPES
#include "openxr/openxr.h"
#include "openxr/openxr_platform.h"
#include <openxr/openxr_reflection.h>
#include <openxr/xr_msft_third_person_observer_private.h>
#include "XR/IUnityXRTrace.h"
#include <chrono>
#include <map>
#include <queue>
#include <string>
#include <unordered_map>
#include "openxr/openxr_reflection.h"
#include "enums_to_string.h"
#include "openxr_utils.h"
class MockRuntime;
extern MockRuntime* s_runtime;
#define GET_PROC_ADDRESS(funcName) \
if (strcmp(#funcName, name) == 0) \
{ \
*function = (PFN_xrVoidFunction)&funcName; \
return XR_SUCCESS; \
}
#define GET_PROC_ADDRESS_REMAP(funcName, funcProc) \
if (strcmp(#funcName, name) == 0) \
{ \
*function = (PFN_xrVoidFunction)&funcProc; \
return XR_SUCCESS; \
}
#define CHECK_RUNTIME() \
if (s_runtime == nullptr) \
return XR_ERROR_HANDLE_INVALID;
#define CHECK_INSTANCE(instance) \
if (s_runtime == nullptr || s_runtime->GetInstance() != instance) \
return XR_ERROR_HANDLE_INVALID;
#define CHECK_SESSION(session) \
if (s_runtime == nullptr || s_runtime->GetSession() != session) \
return XR_ERROR_HANDLE_INVALID;
#define CHECK_SUCCESS(body) \
{ \
XrResult result = (body); \
if (result != XR_SUCCESS) \
return result; \
}
#define DEBUG_LOG_EVERY_FUNC_CALL 0
#if DEBUG_LOG_EVERY_FUNC_CALL
#define LOG_FUNC() MOCK_TRACE(kXRLogTypeDebug, "%s: %s", __FILE__, __FUNCTION__)
#else
#define LOG_FUNC()
#endif
XrResult GetProcAddrMockAPI(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
XrResult MockRuntime_BeforeFunction(const char* name);
void MockRuntime_AfterFunction(const char* name, XrResult result);
#define MOCK_HOOK_AFTER_NAMED(name, result) MockRuntime_AfterFunction(name, result);
#define MOCK_HOOK_AFTER(result) MOCK_HOOK_AFTER_NAMED(__FUNCTION__, result);
#define MOCK_HOOK_BEFORE_NAMED(name) \
XrResult hookResult = MockRuntime_BeforeFunction(name); \
if (hookResult != XR_SUCCESS) \
{ \
MOCK_HOOK_AFTER_NAMED(name, hookResult); \
return hookResult; \
}
#define MOCK_HOOK_BEFORE() MOCK_HOOK_BEFORE_NAMED(__FUNCTION__)
#define MOCK_HOOK_NAMED(name, x) \
MOCK_HOOK_BEFORE_NAMED(name) \
hookResult = (x); \
MOCK_HOOK_AFTER_NAMED(name, hookResult); \
return hookResult;
#define MOCK_HOOK(x) MOCK_HOOK_NAMED(__FUNCTION__, (x))
#include "mock_events.h"
#include "mock_extensions.h"
#include "mock_input_state.h"
#include "mock_runtime.h"
struct UnityVector3
{
float x;
float y;
float z;
UnityVector3()
{
x = y = z = 0.0f;
}
UnityVector3(const XrVector3f& v)
: x(v.x)
, y(v.y)
, z(-v.z)
{
}
operator XrVector3f() const
{
return XrVector3f{x, y, -z};
}
};
struct UnityVector4
{
float x;
float y;
float z;
float w;
UnityVector4()
{
x = y = z = 0.0f;
}
UnityVector4(const XrFovf& f)
: x(f.angleLeft)
, y(f.angleRight)
, z(f.angleUp)
, w(f.angleDown)
{
}
UnityVector4(const XrQuaternionf& q)
: x(-q.x)
, y(-q.y)
, z(q.z)
, w(q.w)
{
}
operator XrFovf() const
{
return XrFovf{x, y, z, w};
}
operator XrQuaternionf() const
{
return XrQuaternionf{-x, -y, z, w};
}
};

View File

@@ -0,0 +1,391 @@
#include "mock.h"
#ifndef TRAMPOLINE
#define TRAMPOLINE 0
#endif
static PFN_xrGetInstanceProcAddr s_GetInstanceProcAddr = nullptr;
static PFN_xrCreateInstance s_xrCreateInstance = nullptr;
static PFN_xrDestroyInstance s_xrDestroyInstance = nullptr;
static XrInstance s_Instance = XR_NULL_HANDLE;
typedef XrResult(XRAPI_PTR* PFN_BeforeFunctionCallback)(const char* name);
typedef void(XRAPI_PTR* PFN_AfterFunctionCallback)(const char* name, XrResult result);
static PFN_BeforeFunctionCallback s_BeforeFunctionCallback = nullptr;
static PFN_AfterFunctionCallback s_AfterFunctionCallback = nullptr;
static bool s_KeepFunctionCallbacks = false;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API MockRuntime_RegisterFunctionCallbacks(PFN_BeforeFunctionCallback before, PFN_AfterFunctionCallback after)
{
s_BeforeFunctionCallback = before;
s_AfterFunctionCallback = after;
#if TRAMPOLINE
if (s_Instance == nullptr || s_GetInstanceProcAddr == nullptr)
return;
void (*fptr)(PFN_BeforeFunctionCallback before, PFN_AfterFunctionCallback after) = nullptr;
s_GetInstanceProcAddr(s_Instance, __func__, (PFN_xrVoidFunction*)&fptr);
return fptr(before, after);
#endif
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API MockRuntime_SetKeepFunctionCallbacks(bool value)
{
s_KeepFunctionCallbacks = value;
}
XrResult MockRuntime_BeforeFunction(const char* name)
{
if (s_BeforeFunctionCallback == nullptr)
return XR_SUCCESS;
return s_BeforeFunctionCallback(name);
}
void MockRuntime_AfterFunction(const char* name, XrResult result)
{
if (s_AfterFunctionCallback == nullptr)
return;
s_AfterFunctionCallback(name, result);
}
// Special handling of before / after function callbacks for xrCreateInstance and xrDestroyInstance
extern "C" PFN_xrGetInstanceProcAddr UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API MockRuntime_HookCreateInstance(PFN_xrGetInstanceProcAddr procAddr)
{
s_GetInstanceProcAddr = procAddr;
return (PFN_xrGetInstanceProcAddr)[](XrInstance instance, const char* name, PFN_xrVoidFunction* function)->XrResult
{
XrResult ret = s_GetInstanceProcAddr(instance, name, function);
if (strcmp(name, "xrCreateInstance") == 0)
{
s_xrCreateInstance = (PFN_xrCreateInstance)*function;
*function = (PFN_xrVoidFunction)(PFN_xrCreateInstance)[](const XrInstanceCreateInfo* createInfo, XrInstance* instance)->XrResult
{
XrResult ret = XR_SUCCESS;
if (s_BeforeFunctionCallback != nullptr)
ret = s_BeforeFunctionCallback("xrCreateInstance");
if (XR_FAILED(ret))
return ret;
ret = s_xrCreateInstance(createInfo, instance);
s_Instance = *instance;
if (s_AfterFunctionCallback != nullptr)
s_AfterFunctionCallback("xrCreateInstance", ret);
MockRuntime_RegisterFunctionCallbacks(s_BeforeFunctionCallback, s_AfterFunctionCallback);
return ret;
};
return ret;
}
else if (strcmp(name, "xrDestroyInstance") == 0)
{
s_xrDestroyInstance = (PFN_xrDestroyInstance)*function;
*function = (PFN_xrVoidFunction)(PFN_xrDestroyInstance)[](XrInstance instance)->XrResult
{
PFN_BeforeFunctionCallback before = s_BeforeFunctionCallback;
PFN_AfterFunctionCallback after = s_AfterFunctionCallback;
if (!s_KeepFunctionCallbacks)
{
MockRuntime_RegisterFunctionCallbacks(nullptr, nullptr);
}
XrResult ret = XR_SUCCESS;
if (before != nullptr)
ret = before("xrDestroyInstance");
if (XR_FAILED(ret))
return ret;
ret = s_xrDestroyInstance(instance);
s_Instance = XR_NULL_HANDLE;
if (after != nullptr)
after("xrDestroyInstance", ret);
return ret;
};
return ret;
}
return ret;
};
}
#if TRAMPOLINE
#define MOCK_API_TRAMPOLINE(API_RETURN, DEFAULT_VAL, API_NAME, API_ARGS, API_ARG_NAMES) \
extern "C" API_RETURN UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API API_NAME API_ARGS \
{ \
if (s_Instance == XR_NULL_HANDLE || s_GetInstanceProcAddr == nullptr) \
return DEFAULT_VAL; \
API_RETURN(*fptr) \
API_ARGS = nullptr; \
s_GetInstanceProcAddr(s_Instance, __func__, (PFN_xrVoidFunction*)&fptr); \
return fptr API_ARG_NAMES; \
}
#else
#define MOCK_API_TRAMPOLINE(API_RETURN, DEFAULT_VAL, API_NAME, API_ARGS, API_ARG_NAMES) \
extern "C" API_RETURN UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API API_NAME API_ARGS
#endif
void NO_RETURN()
{
}
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_SetView,
(XrViewConfigurationType viewConfigurationType, int viewIndex, UnityVector3 position, UnityVector4 orientation, UnityVector4 fov),
(viewConfigurationType, viewIndex, position, orientation, fov))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->SetViewPose(viewConfigurationType, viewIndex, {orientation, position}, fov);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_SetViewState,
(XrViewConfigurationType viewConfigurationType, XrViewStateFlags stateFlags),
(viewConfigurationType, stateFlags))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->SetViewStateFlags(viewConfigurationType, stateFlags);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_SetReferenceSpace,
(XrReferenceSpaceType referenceSpace, UnityVector3 position, UnityVector4 orientation, XrSpaceLocationFlags locationFlags),
(referenceSpace, position, orientation, locationFlags))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->SetSpace(referenceSpace, {orientation, position}, locationFlags);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_SetActionSpace,
(XrAction action, UnityVector3 position, UnityVector4 orientation, XrSpaceLocationFlags locationFlags),
(action, position, orientation, locationFlags))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->SetSpace(action, {orientation, position}, locationFlags);
}
#endif
MOCK_API_TRAMPOLINE(XrSessionState, XR_SESSION_STATE_UNKNOWN, MockRuntime_GetSessionState,
(),
())
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return XR_SESSION_STATE_UNKNOWN;
return s_runtime->GetSessionState();
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_RequestExitSession,
(),
())
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->RequestExitSession();
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_CauseInstanceLoss,
(),
())
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->CauseInstanceLoss();
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_CauseUserPresenceChange,
(bool hasUserPresent),
(hasUserPresent))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->CauseUserPresenceChange(hasUserPresent);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_SetReferenceSpaceBounds,
(XrReferenceSpaceType referenceSpaceType, XrExtent2Df bounds),
(referenceSpaceType, bounds))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->SetExtentsForReferenceSpace(referenceSpaceType, bounds);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_GetEndFrameStats,
(int* primaryLayerCount, int* secondaryLayerCount),
(primaryLayerCount, secondaryLayerCount))
#if !TRAMPOLINE
{
*primaryLayerCount = 0;
*secondaryLayerCount = 0;
if (nullptr == s_runtime)
return;
s_runtime->GetEndFrameStats(primaryLayerCount, secondaryLayerCount);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_ActivateSecondaryView,
(XrViewConfigurationType viewConfigurationType, bool activate),
(viewConfigurationType, activate))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->ActivateSecondaryView(viewConfigurationType, activate);
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_RegisterScriptEventCallback,
(PFN_ScriptEventCallback callback),
(callback))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return;
s_runtime->RegisterScriptEventCallback(callback);
}
#endif
MOCK_API_TRAMPOLINE(bool, false, MockRuntime_TransitionToState,
(XrSessionState requestedState, bool forceTransition),
(requestedState, forceTransition))
#if !TRAMPOLINE
{
if (nullptr == s_runtime)
return false;
if (!forceTransition && !s_runtime->IsStateTransitionValid(requestedState))
{
MOCK_TRACE_ERROR("Failed to request state. Was transition valid: %s with force %s",
s_runtime->IsStateTransitionValid(requestedState) ? "TRUE" : "FALSE",
forceTransition ? "TRUE" : "FALSE");
return false;
}
s_runtime->ChangeSessionState(requestedState);
return true;
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_MetaPerformanceMetrics_SeedCounterOnce_Float,
(const char* xrPathString, float value, uint32_t unit),
(xrPathString, value, unit))
#if !TRAMPOLINE
{
MockMetaPerformanceMetrics::Instance()->SeedCounterOnce(
xrPathString,
{XR_SUCCESS,
{XR_TYPE_PERFORMANCE_METRICS_COUNTER_META,
nullptr,
XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META,
static_cast<XrPerformanceMetricsCounterUnitMETA>(unit),
0,
value}});
}
#endif
MOCK_API_TRAMPOLINE(void, NO_RETURN(), MockRuntime_PerformanceSettings_CauseNotification,
(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT level),
(domain, subdomain, level))
#if !TRAMPOLINE
{
if (s_runtime == nullptr)
return;
s_runtime->CausePerformanceSettingsNotification(domain, subdomain, level);
}
#endif
MOCK_API_TRAMPOLINE(XrPerfSettingsLevelEXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT, MockRuntime_PerformanceSettings_GetPerformanceLevelHint,
(XrPerfSettingsDomainEXT domain),
(domain))
#if !TRAMPOLINE
{
if (MockPerformanceSettings::Instance() == nullptr)
return XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT;
return MockPerformanceSettings::Instance()->GetPerformanceLevelHint(domain);
}
#endif
#ifdef XR_USE_PLATFORM_ANDROID
MOCK_API_TRAMPOLINE(bool, false, MockRuntime_IsAndroidThreadTypeRegistered,
(uint32_t threadTypeValue),
(threadTypeValue))
#if !TRAMPOLINE
{
LOG_FUNC();
auto threadType = static_cast<XrAndroidThreadTypeKHR>(threadTypeValue);
return MockAndroidThreadSettings::Instance()->IsAndroidThreadTypeRegistered(threadType);
}
#endif // !TRAMPOLINE
MOCK_API_TRAMPOLINE(uint32_t, 0, MockRuntime_GetRegisteredAndroidThreadsCount,
(),
())
#if !TRAMPOLINE
{
LOG_FUNC();
MOCK_TRACE_DEBUG("Session is valid");
return MockAndroidThreadSettings::Instance()->GetRegisteredAndroidThreadsCount();
}
#endif // !TRAMPOLINE
#endif // XR_USE_PLATFORM_ANDROID
#if !TRAMPOLINE
XrResult GetProcAddrMockAPI(XrInstance instance, const char* name, PFN_xrVoidFunction* function)
{
GET_PROC_ADDRESS(MockRuntime_SetView)
GET_PROC_ADDRESS(MockRuntime_SetViewState)
GET_PROC_ADDRESS(MockRuntime_SetReferenceSpace)
GET_PROC_ADDRESS(MockRuntime_SetActionSpace)
GET_PROC_ADDRESS(MockRuntime_GetSessionState)
GET_PROC_ADDRESS(MockRuntime_RequestExitSession)
GET_PROC_ADDRESS(MockRuntime_CauseInstanceLoss)
GET_PROC_ADDRESS(MockRuntime_CauseUserPresenceChange)
GET_PROC_ADDRESS(MockRuntime_SetReferenceSpaceBounds)
GET_PROC_ADDRESS(MockRuntime_GetEndFrameStats)
GET_PROC_ADDRESS(MockRuntime_ActivateSecondaryView)
GET_PROC_ADDRESS(MockRuntime_RegisterScriptEventCallback)
GET_PROC_ADDRESS(MockRuntime_RegisterFunctionCallbacks)
GET_PROC_ADDRESS(MockRuntime_TransitionToState)
GET_PROC_ADDRESS(MockRuntime_MetaPerformanceMetrics_SeedCounterOnce_Float)
GET_PROC_ADDRESS(MockRuntime_PerformanceSettings_CauseNotification)
GET_PROC_ADDRESS(MockRuntime_PerformanceSettings_GetPerformanceLevelHint)
#ifdef XR_USE_PLATFORM_ANDROID
GET_PROC_ADDRESS(MockRuntime_IsAndroidThreadTypeRegistered)
GET_PROC_ADDRESS(MockRuntime_GetRegisteredAndroidThreadsCount)
#endif // XR_USE_PLATFORM_ANDROID
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
#endif

View File

@@ -0,0 +1,24 @@
// Defines Mock Runtime specific events at the end of the structure type list
const XrStructureType XR_TYPE_EVENT_SCRIPT_EVENT_MOCK = (XrStructureType)(XR_STRUCTURE_TYPE_MAX_ENUM - 1);
// Register a callback that gets called for script events sent by mock
//
typedef enum
{
XR_MOCK_SCRIPT_EVENT_UNKNOWN,
XR_MOCK_SCRIPT_EVENT_END_FRAME,
XR_MOCK_SCRIPT_EVENT_HAPTIC_IMPULSE,
XR_MOCK_SCRIPT_EVENT_HAPTIC_STOP
} XrMockScriptEvent;
typedef struct XrEventScriptEventMOCK
{
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrMockScriptEvent event;
uint64_t param;
} XrEventScriptEventMOCK;
typedef void (*PFN_ScriptEventCallback)(XrMockScriptEvent event, uint64_t param);

View File

@@ -0,0 +1,33 @@
#pragma once
#include "Extensions/mock_khr_android_thread_settings.h"
#include "Extensions/mock_meta_performance_metrics.h"
#include "Extensions/mock_performance_settings.h"
// XR_EXT_conformance_automation
struct ConformanceAutomation;
class MockInputState;
void ConformanceAutomation_Create();
void ConformanceAutomation_Destroy();
XrResult ConformanceAutomation_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
XrResult ConformanceAutomation_GetInputState(MockInputState* state);
bool ConformanceAutomation_IsActive(XrPath interactionProfile, XrPath userPath, bool defaultValue = true);
// XR_KHR_VULKAN_ENABLE2
#if defined(XR_USE_GRAPHICS_API_VULKAN)
XrResult MockVulkan_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
#endif
// XR_KHR_D3D11_ENABLE
#if defined(XR_USE_GRAPHICS_API_D3D11)
XrResult MockD3D11_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
#endif
// XR_KHR_D3D12_ENABLE
#if defined(XR_USE_GRAPHICS_API_D3D12)
XrResult MockD3D12_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
#endif

View File

@@ -0,0 +1,227 @@
#include "mock.h"
void MockInputState::Reset()
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
value.boolValue = false;
break;
case XR_ACTION_TYPE_FLOAT_INPUT:
value.floatValue = false;
break;
case XR_ACTION_TYPE_VECTOR2F_INPUT:
value.vectorValue = {0, 0};
break;
case XR_ACTION_TYPE_POSE_INPUT:
value.locationValue.pose = {{0, 0, 0, 1}, {0, 0, 0}};
value.locationValue.space = XR_NULL_HANDLE;
value.locationValue.linearVelocityValid = false;
value.locationValue.linearVelocity = {0, 0, 0};
value.locationValue.angularVelocityValid = false;
value.locationValue.angularVelocity = {0, 0, 0};
break;
default:
break;
}
}
void MockInputState::Set(float v)
{
switch (type)
{
case XR_ACTION_TYPE_FLOAT_INPUT:
value.floatValue = v;
break;
case XR_ACTION_TYPE_BOOLEAN_INPUT:
value.boolValue = v != 0.0f;
break;
default:
value.floatValue = 0.0f;
break;
}
}
void MockInputState::Set(XrBool32 v)
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
value.boolValue = v;
break;
case XR_ACTION_TYPE_FLOAT_INPUT:
value.floatValue = v ? 1.0f : 0.0f;
break;
default:
value.boolValue = false;
break;
}
}
void MockInputState::Set(XrVector2f v)
{
if (type != XR_ACTION_TYPE_VECTOR2F_INPUT)
{
Reset();
return;
}
value.vectorValue = v;
}
void MockInputState::Set(XrSpace space, XrPosef pose)
{
if (type != XR_ACTION_TYPE_POSE_INPUT)
{
Reset();
return;
}
value.locationValue.space = space;
value.locationValue.pose = pose;
}
void MockInputState::SetVelocity(bool linearValid, XrVector3f linear, bool angularValid, XrVector3f angular)
{
value.locationValue.linearVelocityValid = linearValid;
value.locationValue.linearVelocity = linearValid ? linear : XrVector3f{0, 0, 0};
value.locationValue.angularVelocityValid = angularValid;
value.locationValue.angularVelocity = angularValid ? angular : XrVector3f{0, 0, 0};
}
float MockInputState::GetFloat() const
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
return (float)value.boolValue;
case XR_ACTION_TYPE_FLOAT_INPUT:
return value.floatValue;
default:
break;
}
return 0.0f;
}
XrBool32 MockInputState::GetBoolean() const
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
return value.boolValue;
case XR_ACTION_TYPE_FLOAT_INPUT:
return value.floatValue != 0.0f;
default:
break;
}
return false;
}
XrVector2f MockInputState::GetVector2() const
{
if (type == XR_ACTION_TYPE_VECTOR2F_INPUT)
return value.vectorValue;
return XrVector2f();
}
XrSpace MockInputState::GetLocationSpace() const
{
if (type == XR_ACTION_TYPE_POSE_INPUT)
return value.locationValue.space;
return XR_NULL_HANDLE;
}
XrPosef MockInputState::GetLocationPose() const
{
if (type == XR_ACTION_TYPE_POSE_INPUT)
return value.locationValue.pose;
return XrPosef();
}
bool MockInputState::HasLinearVelocity() const
{
return type == XR_ACTION_TYPE_POSE_INPUT && value.locationValue.linearVelocityValid;
}
XrVector3f MockInputState::GetLinearVelocity() const
{
if (HasLinearVelocity())
return value.locationValue.linearVelocity;
return XrVector3f{};
}
bool MockInputState::HasAngularVelocity() const
{
return type == XR_ACTION_TYPE_POSE_INPUT && value.locationValue.angularVelocityValid;
}
XrVector3f MockInputState::GetAngularVelocity() const
{
if (type == XR_ACTION_TYPE_POSE_INPUT)
return value.locationValue.angularVelocity;
return XrVector3f{};
}
bool MockInputState::IsCompatibleType(XrActionType actionType) const
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
case XR_ACTION_TYPE_FLOAT_INPUT:
return actionType == XR_ACTION_TYPE_FLOAT_INPUT || actionType == XR_ACTION_TYPE_BOOLEAN_INPUT;
default:
break;
}
return IsType(actionType);
}
void MockInputState::CopyValue(const MockInputState& state)
{
switch (type)
{
case XR_ACTION_TYPE_BOOLEAN_INPUT:
value.boolValue = state.GetBoolean();
break;
case XR_ACTION_TYPE_FLOAT_INPUT:
value.floatValue = state.GetFloat();
break;
case XR_ACTION_TYPE_VECTOR2F_INPUT:
value.vectorValue = state.GetVector2();
break;
case XR_ACTION_TYPE_POSE_INPUT:
value.locationValue.space = state.GetLocationSpace();
value.locationValue.pose = state.GetLocationPose();
value.locationValue.angularVelocityValid = state.HasAngularVelocity();
value.locationValue.angularVelocity = state.GetAngularVelocity();
value.locationValue.linearVelocityValid = state.HasLinearVelocity();
value.locationValue.linearVelocity = state.GetLinearVelocity();
break;
default:
break;
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
class MockInputState
{
public:
XrPath interactionProfile;
XrPath path;
XrActionType type;
const char* localizedName;
bool IsType(XrActionType actionType) const
{
return type == actionType;
}
bool IsCompatibleType(XrActionType actionType) const;
void Reset();
void Set(float value);
void Set(XrBool32 value);
void Set(XrVector2f value);
void Set(XrSpace space, XrPosef pose);
void SetVelocity(bool linearValid, XrVector3f linear, bool angularValid, XrVector3f angular);
void CopyValue(const MockInputState& state);
float GetFloat() const;
XrBool32 GetBoolean() const;
XrVector2f GetVector2() const;
XrSpace GetLocationSpace() const;
XrPosef GetLocationPose() const;
bool HasAngularVelocity() const;
bool HasLinearVelocity() const;
XrVector3f GetAngularVelocity() const;
XrVector3f GetLinearVelocity() const;
private:
union
{
XrBool32 boolValue;
float floatValue;
XrVector2f vectorValue;
struct
{
XrSpace space;
XrPosef pose;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
bool linearVelocityValid;
bool angularVelocityValid;
} locationValue;
} value;
};

View File

@@ -0,0 +1,902 @@
#include "mock.h"
#include <openxr/loader_interfaces.h>
IUnityXRTrace* s_Trace = nullptr;
MockRuntime* s_runtime = nullptr;
uint64_t s_nextInstanceId = 11; // Start at 11 because 10 is a special test case
#define XR_UNITY_mock_test_SPEC_VERSION 123
#define XR_UNITY_MOCK_TEST_EXTENSION_NAME "XR_UNITY_mock_test"
#define XR_UNITY_null_gfx_SPEC_VERSION 1
#define XR_UNITY_NULL_GFX_EXTENSION_NAME "XR_UNITY_null_gfx"
#define XR_UNITY_android_present_SPEC_VERSION 1
#define XR_UNITY_ANDROID_PRESENT_EXTENSION_NAME "XR_UNITY_android_present"
#define ENUM_TO_STR(name, val) \
case val: \
strncpy(buffer, #name, XR_MAX_RESULT_STRING_SIZE - 1); \
break;
// clang-format off
static XrExtensionProperties s_Extensions[] = {
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_UNITY_MOCK_TEST_EXTENSION_NAME,
XR_UNITY_mock_test_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_UNITY_NULL_GFX_EXTENSION_NAME,
XR_UNITY_null_gfx_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_UNITY_ANDROID_PRESENT_EXTENSION_NAME,
XR_UNITY_android_present_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_VISIBILITY_MASK_EXTENSION_NAME,
XR_KHR_visibility_mask_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME,
XR_EXT_conformance_automation_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME,
XR_KHR_composition_layer_depth_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_VARJO_QUAD_VIEWS_EXTENSION_NAME,
XR_VARJO_quad_views_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME,
XR_MSFT_secondary_view_configuration_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME,
XR_EXT_eye_gaze_interaction_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_MSFT_HAND_INTERACTION_EXTENSION_NAME,
XR_MSFT_hand_interaction_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_HAND_INTERACTION_EXTENSION_NAME,
XR_EXT_hand_interaction_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME,
XR_FB_touch_controller_pro_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME,
XR_MSFT_first_person_observer_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_MSFT_THIRD_PERSON_OBSERVER_PRIVATE_EXTENSION_NAME,
XR_MSFT_third_person_observer_private_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_META_PERFORMANCE_METRICS_EXTENSION_NAME,
XR_META_performance_metrics_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME,
XR_META_touch_controller_plus_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME,
XR_EXT_hp_mixed_reality_controller_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_USER_PRESENCE_EXTENSION_NAME,
XR_EXT_user_presence_SPEC_VERSION
},
{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME,
XR_EXT_performance_settings_SPEC_VERSION
}
#if defined(XR_USE_PLATFORM_ANDROID)
,{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
XR_KHR_android_thread_settings_SPEC_VERSION
}
#endif
#if defined(XR_USE_GRAPHICS_API_VULKAN)
,{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME,
XR_KHR_vulkan_enable2_SPEC_VERSION
}
#endif
#if defined(XR_USE_GRAPHICS_API_D3D11)
,{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_D3D11_ENABLE_EXTENSION_NAME,
XR_KHR_D3D11_enable_SPEC_VERSION
}
#endif
#if defined(XR_USE_GRAPHICS_API_D3D12)
,{
XR_TYPE_EXTENSION_PROPERTIES,
nullptr,
XR_KHR_D3D12_ENABLE_EXTENSION_NAME,
XR_KHR_D3D12_enable_SPEC_VERSION
}
#endif
};
// clang-format on
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrApiLayerProperties* properties)
{
LOG_FUNC();
*propertyCountOutput = 0;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateInstanceExtensionProperties(const char* layerName, uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrExtensionProperties* properties)
{
LOG_FUNC();
*propertyCountOutput = sizeof(s_Extensions) / sizeof(XrExtensionProperties);
if (propertyCapacityInput == 0)
return XR_SUCCESS;
if (propertyCapacityInput < *propertyCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
uint32_t count = 0;
while (count < *propertyCountOutput)
{
properties[count] = s_Extensions[count];
++count;
}
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateInstance(const XrInstanceCreateInfo* createInfo, XrInstance* instance)
{
LOG_FUNC();
// Destroy any existing runtime if there is one
if (s_runtime != nullptr)
{
delete s_runtime;
s_runtime = nullptr;
}
*instance = 0;
MockRuntimeCreateFlags flags = 0;
for (uint32_t i = 0; i < createInfo->enabledExtensionCount; ++i)
{
const char* extension = createInfo->enabledExtensionNames[i];
if (strncmp(XR_UNITY_MOCK_TEST_EXTENSION_NAME, extension, sizeof(XR_UNITY_MOCK_TEST_EXTENSION_NAME)) == 0)
{
*instance = (XrInstance)10;
continue;
}
if ((flags & MR_CREATE_ALL_GFX_EXT) == 0)
{
#if defined(XR_USE_GRAPHICS_API_VULKAN)
if (strncmp(XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME, extension, sizeof(XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_VULKAN_GFX_EXT;
continue;
}
#endif
#if defined(XR_USE_GRAPHICS_API_D3D11)
if (strncmp(XR_KHR_D3D11_ENABLE_EXTENSION_NAME, extension, sizeof(XR_KHR_D3D11_ENABLE_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_D3D11_GFX_EXT;
continue;
}
#endif
#if defined(XR_USE_GRAPHICS_API_D3D12)
if (strncmp(XR_KHR_D3D12_ENABLE_EXTENSION_NAME, extension, sizeof(XR_KHR_D3D12_ENABLE_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_D3D12_GFX_EXT;
continue;
}
#endif
if (strncmp(XR_UNITY_NULL_GFX_EXTENSION_NAME, extension, sizeof(XR_UNITY_NULL_GFX_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_NULL_GFX_EXT;
continue;
}
}
// Conformance Automation
if (strncmp(XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME, extension, sizeof(XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_CONFORMANCE_AUTOMATION_EXT;
continue;
}
if (strncmp(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME, extension, sizeof(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_COMPOSITION_LAYER_DEPTH_EXT;
continue;
}
if (strncmp(XR_VARJO_QUAD_VIEWS_EXTENSION_NAME, extension, sizeof(XR_VARJO_QUAD_VIEWS_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_VARJO_QUAD_VIEWS_EXT;
continue;
}
if (strncmp(XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME, extension, sizeof(XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_MSFT_SECONDARY_VIEW_CONFIGURATION_EXT;
continue;
}
if (strncmp(XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME, extension, sizeof(XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_MSFT_FIRST_PERSON_OBSERVER_EXT;
continue;
}
if (strncmp(XR_MSFT_THIRD_PERSON_OBSERVER_PRIVATE_EXTENSION_NAME, extension, sizeof(XR_MSFT_THIRD_PERSON_OBSERVER_PRIVATE_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_MSFT_THIRD_PERSON_OBSERVER_EXT;
continue;
}
if (strncmp(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME, extension, sizeof(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_EYE_GAZE_INTERACTION_EXT;
continue;
}
if (strncmp(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME, extension, sizeof(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_MSFT_HAND_INTERACTION_EXT;
continue;
}
if (strncmp(XR_EXT_HAND_INTERACTION_EXTENSION_NAME, extension, sizeof(XR_EXT_HAND_INTERACTION_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_HAND_INTERACTION_EXT;
continue;
}
if (strncmp(XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME, extension, sizeof(XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_FB_TOUCH_CONTROLLER_PRO;
continue;
}
if (strncmp(XR_EXT_USER_PRESENCE_EXTENSION_NAME, extension, sizeof(XR_EXT_USER_PRESENCE_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_USER_PRESENCE_EXT;
continue;
}
if (strncmp(XR_META_PERFORMANCE_METRICS_EXTENSION_NAME, extension, sizeof(XR_META_PERFORMANCE_METRICS_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_META_PERFORMANCE_METRICS_EXT;
}
if (strncmp(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME, extension, sizeof(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_HP_REVERB_G2_CONTROLLER;
}
if (strncmp(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME, extension, sizeof(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_PERFORMANCE_SETTINGS_EXT;
}
if (strncmp(XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME, extension, sizeof(XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_META_TOUCH_CONTROLLER_PLUS;
continue;
}
#ifdef XR_USE_PLATFORM_ANDROID
if (strncmp(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME, extension, sizeof(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME)) == 0)
{
flags |= MR_CREATE_KHR_ANDROID_THREAD_SETTINGS_EXT;
}
#endif
}
if ((flags & MR_CREATE_ALL_GFX_EXT) == 0)
flags |= MR_CREATE_NULL_GFX_EXT;
// Assign an instance id if one was not given
if (*instance == 0)
*instance = (XrInstance)(s_nextInstanceId++);
s_runtime = new MockRuntime(*instance, flags);
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroyInstance(XrInstance instance)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK_BEFORE();
delete s_runtime;
s_runtime = nullptr;
MOCK_HOOK_AFTER(XR_SUCCESS);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInstanceProperties(XrInstance instance, XrInstanceProperties* instanceProperties)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
instanceProperties->runtimeVersion = XR_MAKE_VERSION(0, 0, 2);
strncpy(instanceProperties->runtimeName, "Unity Mock Runtime", XR_MAX_RUNTIME_NAME_SIZE);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrPollEvent(XrInstance instance, XrEventDataBuffer* eventData)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->GetNextEvent(eventData));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrResultToString(XrInstance instance, XrResult value, char buffer[XR_MAX_RESULT_STRING_SIZE])
{
LOG_FUNC();
CHECK_INSTANCE(instance);
switch (value)
{
XR_LIST_ENUM_XrResult(ENUM_TO_STR) default : strncpy(buffer, ((value < 0 ? "XR_UNKNOWN_FAILURE_" : "XR_UNKNOWN_SUCCESS_") + std::to_string(value)).c_str(), XR_MAX_RESULT_STRING_SIZE - 1);
break;
}
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrStructureTypeToString(XrInstance instance, XrStructureType value, char buffer[XR_MAX_STRUCTURE_NAME_SIZE])
{
LOG_FUNC();
CHECK_INSTANCE(instance);
switch (value)
{
XR_LIST_ENUM_XrStructureType(ENUM_TO_STR) default : strncpy(buffer, ("XR_UNKNOWN_STRUCTURE_TYPE_" + std::to_string(value)).c_str(), XR_MAX_RESULT_STRING_SIZE - 1);
break;
}
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetSystem(XrInstance instance, const XrSystemGetInfo* getInfo, XrSystemId* systemId)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
*systemId = (XrSystemId)2;
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetSystemProperties(XrInstance instance, XrSystemId systemId, XrSystemProperties* properties)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->GetSystemProperties(systemId, properties));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateEnvironmentBlendModes(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t* environmentBlendModeCountOutput, XrEnvironmentBlendMode* environmentBlendModes)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->EnumerateEnvironmentBlendModes(systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK_BEFORE();
XrResult result = s_runtime->CreateSession(createInfo);
if (result == XR_SUCCESS)
*session = s_runtime->GetSession();
MOCK_HOOK_AFTER(result);
return result;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroySession(XrSession session)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->DestroySession());
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateReferenceSpaces(XrSession session, uint32_t spaceCapacityInput, uint32_t* spaceCountOutput, XrReferenceSpaceType* spaces)
{
LOG_FUNC();
CHECK_SESSION(session);
if (!spaceCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
if (s_runtime->IsLocalFloorSpaceEnabled())
{
*spaceCountOutput = 5;
}
else
{
*spaceCountOutput = 4;
}
if (spaceCapacityInput == 0)
return XR_SUCCESS;
if (spaceCapacityInput < *spaceCountOutput || !spaces)
return XR_ERROR_VALIDATION_FAILURE;
spaces[0] = XR_REFERENCE_SPACE_TYPE_VIEW;
spaces[1] = XR_REFERENCE_SPACE_TYPE_LOCAL;
spaces[2] = XR_REFERENCE_SPACE_TYPE_STAGE;
spaces[3] = XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT;
if (s_runtime->IsLocalFloorSpaceEnabled())
{
spaces[4] = XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT;
}
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateReferenceSpace(XrSession session, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->CreateReferenceSpace(createInfo, space));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetReferenceSpaceBoundsRect(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df* bounds)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetReferenceSpaceBoundsRect(referenceSpaceType, bounds));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateActionSpace(XrSession session, const XrActionSpaceCreateInfo* createInfo, XrSpace* space)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->CreateActionSpace(createInfo, space));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location)
{
LOG_FUNC();
CHECK_RUNTIME();
MOCK_HOOK(s_runtime->LocateSpace(space, baseSpace, time, location));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroySpace(XrSpace space)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t* viewConfigurationTypeCountOutput, XrViewConfigurationType* viewConfigurationTypes)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->EnumerateViewConfigurations(systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties* configurationProperties)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateViewConfigurationViews(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrViewConfigurationView* views)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->EnumerateViewConfigurationViews(systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
{
LOG_FUNC();
*formatCountOutput = 1;
if (formatCapacityInput == 0)
return XR_SUCCESS;
if (formatCapacityInput < *formatCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
formats[0] = 0;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
{
LOG_FUNC();
static uint64_t uniqueSwapchainHandle = 0;
*swapchain = (XrSwapchain)++uniqueSwapchainHandle;
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroySwapchain(XrSwapchain swapchain)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
{
LOG_FUNC();
*imageCountOutput = 1;
if (imageCapacityInput == 0)
return XR_SUCCESS;
if (imageCapacityInput < *imageCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
{
LOG_FUNC();
*index = 0;
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrWaitSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageWaitInfo* waitInfo)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrBeginSession(XrSession session, const XrSessionBeginInfo* beginInfo)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->BeginSession(beginInfo));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEndSession(XrSession session)
{
LOG_FUNC();
CHECK_SESSION(session);
//CHECK_EXPECTED_RESULT(XR_SUCCESS, XR_ERROR_SESSION_NOT_STOPPING);
MOCK_HOOK(s_runtime->EndSession());
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrRequestExitSession(XrSession session)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->RequestExitSession());
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrWaitFrame(XrSession session, const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->WaitFrame(frameWaitInfo, frameState));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrBeginFrame(XrSession session, const XrFrameBeginInfo* frameBeginInfo)
{
LOG_FUNC();
MOCK_HOOK(XR_SUCCESS);
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEndFrame(XrSession session, const XrFrameEndInfo* frameEndInfo)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->EndFrame(frameEndInfo));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrLocateViews(XrSession session, const XrViewLocateInfo* viewLocateInfo, XrViewState* viewState, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrView* views)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->LocateViews(viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrStringToPath(XrInstance instance, const char* pathString, XrPath* path)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->StringToPath(pathString, path));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrPathToString(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->PathToString(path, bufferCapacityInput, bufferCountOutput, buffer));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateActionSet(XrInstance instance, const XrActionSetCreateInfo* createInfo, XrActionSet* actionSet)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->CreateActionSet(createInfo, actionSet));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroyActionSet(XrActionSet actionSet)
{
LOG_FUNC();
CHECK_RUNTIME();
MOCK_HOOK(s_runtime->DestroyActionSet(actionSet));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateAction(XrActionSet actionSet, const XrActionCreateInfo* createInfo, XrAction* action)
{
LOG_FUNC();
CHECK_RUNTIME();
MOCK_HOOK(s_runtime->CreateAction(actionSet, createInfo, action));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrDestroyAction(XrAction action)
{
LOG_FUNC();
CHECK_RUNTIME();
MOCK_HOOK(s_runtime->DestroyAction(action));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSuggestInteractionProfileBindings(XrInstance instance, const XrInteractionProfileSuggestedBinding* suggestedBindings)
{
LOG_FUNC();
CHECK_INSTANCE(instance);
MOCK_HOOK(s_runtime->SuggestInteractionProfileBindings(suggestedBindings));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttachInfo* attachInfo)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->AttachSessionActionSets(attachInfo));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetCurrentInteractionProfile(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState* interactionProfile)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetCurrentInteractionProfile(topLevelUserPath, interactionProfile));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetActionStateBoolean(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateBoolean* state)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetActionStateBoolean(getInfo, state));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetActionStateFloat(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateFloat* state)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetActionStateFloat(getInfo, state));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetActionStateVector2f(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateVector2f* state)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetActionStateVector2f(getInfo, state));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetActionStatePose(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStatePose* state)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetActionStatePose(getInfo, state));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSyncActions(XrSession session, const XrActionsSyncInfo* syncInfo)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->SyncActions(syncInfo));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEnumerateBoundSourcesForAction(XrSession session, const XrBoundSourcesForActionEnumerateInfo* enumerateInfo, uint32_t sourceCapacityInput, uint32_t* sourceCountOutput, XrPath* sources)
{
LOG_FUNC();
CHECK_SESSION(session)
MOCK_HOOK(s_runtime->EnumerateBoundSourcesForAction(enumerateInfo, sourceCapacityInput, sourceCountOutput, sources));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInputSourceLocalizedName(XrSession session, const XrInputSourceLocalizedNameGetInfo* getInfo, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->GetInputSourceLocalizedName(getInfo, bufferCapacityInput, bufferCountOutput, buffer));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrApplyHapticFeedback(XrSession session, const XrHapticActionInfo* hapticActionInfo, const XrHapticBaseHeader* hapticFeedback)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->ApplyHapticFeedback(hapticActionInfo, hapticFeedback));
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrStopHapticFeedback(XrSession session, const XrHapticActionInfo* hapticActionInfo)
{
LOG_FUNC();
CHECK_SESSION(session);
MOCK_HOOK(s_runtime->StopHapticFeedback(hapticActionInfo));
}
extern uint32_t s_VisibilityMaskVerticesSizes[2][3];
extern uint32_t s_VisibilityMaskIndicesSizes[2][3];
extern XrVector2f s_VisibilityMaskVertices[2][3][99];
extern uint32_t s_VisibilityMaskIndices[2][3][200];
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR* visibilityMask)
{
const uint32_t visiblityMaskTypeLookup = visibilityMaskType - 1;
visibilityMask->vertexCountOutput = s_VisibilityMaskVerticesSizes[viewIndex][visiblityMaskTypeLookup];
visibilityMask->indexCountOutput = s_VisibilityMaskIndicesSizes[viewIndex][visiblityMaskTypeLookup];
if (visibilityMask->vertexCapacityInput == 0 || visibilityMask->indexCapacityInput == 0)
return XR_SUCCESS;
if (visibilityMask->vertexCapacityInput < visibilityMask->vertexCountOutput ||
visibilityMask->indexCapacityInput < visibilityMask->indexCountOutput)
return XR_ERROR_VALIDATION_FAILURE;
memcpy(visibilityMask->vertices, &s_VisibilityMaskVertices[viewIndex][visiblityMaskTypeLookup], sizeof(XrVector2f) * visibilityMask->vertexCountOutput);
memcpy(visibilityMask->indices, &s_VisibilityMaskIndices[viewIndex][visiblityMaskTypeLookup], sizeof(uint32_t) * visibilityMask->indexCountOutput);
return XR_SUCCESS;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function)
{
LOG_FUNC();
if (s_runtime != nullptr && XR_SUCCESS == s_runtime->GetInstanceProcAddr(name, function))
return XR_SUCCESS;
GET_PROC_ADDRESS(xrEnumerateApiLayerProperties)
GET_PROC_ADDRESS(xrEnumerateInstanceExtensionProperties)
GET_PROC_ADDRESS(xrCreateInstance)
GET_PROC_ADDRESS(xrDestroyInstance)
GET_PROC_ADDRESS(xrGetInstanceProperties)
GET_PROC_ADDRESS(xrPollEvent)
GET_PROC_ADDRESS(xrResultToString)
GET_PROC_ADDRESS(xrStructureTypeToString)
GET_PROC_ADDRESS(xrGetSystem)
GET_PROC_ADDRESS(xrGetSystemProperties)
GET_PROC_ADDRESS(xrEnumerateEnvironmentBlendModes)
GET_PROC_ADDRESS(xrCreateSession)
GET_PROC_ADDRESS(xrDestroySession)
GET_PROC_ADDRESS(xrEnumerateReferenceSpaces)
GET_PROC_ADDRESS(xrCreateReferenceSpace)
GET_PROC_ADDRESS(xrGetReferenceSpaceBoundsRect)
GET_PROC_ADDRESS(xrCreateActionSpace)
GET_PROC_ADDRESS(xrLocateSpace)
GET_PROC_ADDRESS(xrDestroySpace)
GET_PROC_ADDRESS(xrEnumerateViewConfigurations)
GET_PROC_ADDRESS(xrGetViewConfigurationProperties)
GET_PROC_ADDRESS(xrEnumerateViewConfigurationViews)
GET_PROC_ADDRESS(xrEnumerateSwapchainFormats)
GET_PROC_ADDRESS(xrCreateSwapchain)
GET_PROC_ADDRESS(xrDestroySwapchain)
GET_PROC_ADDRESS(xrEnumerateSwapchainImages)
GET_PROC_ADDRESS(xrAcquireSwapchainImage)
GET_PROC_ADDRESS(xrWaitSwapchainImage)
GET_PROC_ADDRESS(xrReleaseSwapchainImage)
GET_PROC_ADDRESS(xrBeginSession)
GET_PROC_ADDRESS(xrEndSession)
GET_PROC_ADDRESS(xrRequestExitSession)
GET_PROC_ADDRESS(xrWaitFrame)
GET_PROC_ADDRESS(xrBeginFrame)
GET_PROC_ADDRESS(xrEndFrame)
GET_PROC_ADDRESS(xrLocateViews)
GET_PROC_ADDRESS(xrStringToPath)
GET_PROC_ADDRESS(xrPathToString)
GET_PROC_ADDRESS(xrCreateActionSet)
GET_PROC_ADDRESS(xrDestroyActionSet)
GET_PROC_ADDRESS(xrCreateAction)
GET_PROC_ADDRESS(xrDestroyAction)
GET_PROC_ADDRESS(xrSuggestInteractionProfileBindings)
GET_PROC_ADDRESS(xrAttachSessionActionSets)
GET_PROC_ADDRESS(xrGetCurrentInteractionProfile)
GET_PROC_ADDRESS(xrGetActionStateBoolean)
GET_PROC_ADDRESS(xrGetActionStateFloat)
GET_PROC_ADDRESS(xrGetActionStateVector2f)
GET_PROC_ADDRESS(xrGetActionStatePose)
GET_PROC_ADDRESS(xrSyncActions)
GET_PROC_ADDRESS(xrEnumerateBoundSourcesForAction)
GET_PROC_ADDRESS(xrGetInputSourceLocalizedName)
GET_PROC_ADDRESS(xrApplyHapticFeedback)
GET_PROC_ADDRESS(xrStopHapticFeedback)
GET_PROC_ADDRESS(xrGetVisibilityMaskKHR)
if (XR_SUCCEEDED(GetProcAddrMockAPI(instance, name, function)))
return XR_SUCCESS;
return XR_ERROR_FUNCTION_UNSUPPORTED;
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetXRTrace(IUnityXRTrace* trace)
{
s_Trace = trace;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrNegotiateLoaderRuntimeInterface(const XrNegotiateLoaderInfo* loaderInfo, XrNegotiateRuntimeRequest* runtimeRequest)
{
runtimeRequest->getInstanceProcAddr = xrGetInstanceProcAddr;
runtimeRequest->runtimeApiVersion = XR_CURRENT_API_VERSION;
runtimeRequest->runtimeInterfaceVersion = 1;
return XR_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,396 @@
#pragma once
typedef XrFlags64 MockRuntimeCreateFlags;
static const MockRuntimeCreateFlags MR_CREATE_DRIVER_EXT = 0x00000001;
static const MockRuntimeCreateFlags MR_CREATE_NULL_GFX_EXT = 0x00000002;
static const MockRuntimeCreateFlags MR_CREATE_CONFORMANCE_AUTOMATION_EXT = 0x00000004;
static const MockRuntimeCreateFlags MR_CREATE_COMPOSITION_LAYER_DEPTH_EXT = 0x00000008;
static const MockRuntimeCreateFlags MR_CREATE_VULKAN_GFX_EXT = 0x00000010;
static const MockRuntimeCreateFlags MR_CREATE_D3D11_GFX_EXT = 0x00000020;
static const MockRuntimeCreateFlags MR_CREATE_VARJO_QUAD_VIEWS_EXT = 0x00000040;
static const MockRuntimeCreateFlags MR_CREATE_MSFT_SECONDARY_VIEW_CONFIGURATION_EXT = 0x00000080;
static const MockRuntimeCreateFlags MR_CREATE_MSFT_FIRST_PERSON_OBSERVER_EXT = 0x00000100;
static const MockRuntimeCreateFlags MR_CREATE_EYE_GAZE_INTERACTION_EXT = 0x00000200;
static const MockRuntimeCreateFlags MR_CREATE_MSFT_HAND_INTERACTION_EXT = 0x00000400;
static const MockRuntimeCreateFlags MR_CREATE_MSFT_THIRD_PERSON_OBSERVER_EXT = 0x00000800;
static const MockRuntimeCreateFlags MR_CREATE_FB_TOUCH_CONTROLLER_PRO = 0x00001000;
static const MockRuntimeCreateFlags MR_CREATE_META_PERFORMANCE_METRICS_EXT = 0x00002000;
static const MockRuntimeCreateFlags MR_CREATE_HP_REVERB_G2_CONTROLLER = 0x00004000;
static const MockRuntimeCreateFlags MR_CREATE_HAND_INTERACTION_EXT = 0x00008000;
static const MockRuntimeCreateFlags MR_CREATE_D3D12_GFX_EXT = 0x00020000;
static const MockRuntimeCreateFlags MR_CREATE_PERFORMANCE_SETTINGS_EXT = 0x00040000;
static const MockRuntimeCreateFlags MR_CREATE_USER_PRESENCE_EXT = 0x00080000;
static const MockRuntimeCreateFlags MR_CREATE_KHR_ANDROID_THREAD_SETTINGS_EXT = 0x00100000;
static const MockRuntimeCreateFlags MR_CREATE_META_TOUCH_CONTROLLER_PLUS = 0x00200000;
static const MockRuntimeCreateFlags MR_CREATE_ALL_GFX_EXT = MR_CREATE_VULKAN_GFX_EXT | MR_CREATE_NULL_GFX_EXT | MR_CREATE_D3D11_GFX_EXT | MR_CREATE_D3D12_GFX_EXT;
class MockRuntime
{
public:
MockRuntime(XrInstance instance, MockRuntimeCreateFlags flags);
~MockRuntime();
XrInstance GetInstance() const
{
return instance;
}
XrSession GetSession() const
{
return session;
}
XrSessionState GetSessionState() const
{
return currentState;
}
bool HasValidSession() const
{
return session != XR_NULL_HANDLE;
}
bool HasValidInstance() const
{
return instance != XR_NULL_HANDLE;
}
bool IsSessionState(XrSessionState state) const
{
return currentState == state;
}
bool IsConformanceAutomationEnabled() const
{
return (createFlags & MR_CREATE_CONFORMANCE_AUTOMATION_EXT) != 0;
}
bool IsLocalFloorSpaceEnabled() const
{
return true;
}
XrResult GetNextEvent(XrEventDataBuffer* eventData);
XrResult CreateSession(const XrSessionCreateInfo* createInfo);
XrResult BeginSession(const XrSessionBeginInfo* beginInfo);
XrResult EndSession();
XrResult DestroySession();
void SetMockSession(XrInstance instance, XrSession* session);
void SetSupportingDriverExtension(XrInstance instance, bool usingExtension);
bool IsStateTransitionValid(XrSessionState newState) const;
bool ChangeSessionStateFrom(XrSessionState fromState, XrSessionState toState);
void ChangeSessionState(XrSessionState state);
bool IsSessionRunning() const
{
return isRunning;
}
XrResult RequestExitSession();
bool HasExitBeenRequested() const
{
return exitSessionRequested;
}
void SetExtentsForReferenceSpace(XrReferenceSpaceType referenceSpace, XrExtent2Df extents);
XrResult GetReferenceSpaceBoundsRect(XrReferenceSpaceType referenceSpace, XrExtent2Df* extents);
XrResult CauseInstanceLoss();
XrResult CauseUserPresenceChange(bool hasUserPresent);
bool IsInstanceLost(XrInstance instance) const
{
return instanceIsLost;
};
void SetNullGfx(bool nullGfx);
bool IsNullGfx() const
{
return (createFlags & MR_CREATE_NULL_GFX_EXT) != 0;
}
bool IsVulkanGfx() const
{
return (createFlags & MR_CREATE_VULKAN_GFX_EXT) != 0;
}
bool IsD3D11Gfx() const
{
return (createFlags & MR_CREATE_D3D11_GFX_EXT) != 0;
}
bool IsD3D12Gfx() const
{
return (createFlags & MR_CREATE_D3D12_GFX_EXT) != 0;
}
XrResult WaitFrame(const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState);
XrResult LocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location);
void SetSpace(XrReferenceSpaceType referenceSpaceType, XrPosef pose, XrSpaceLocationFlags spaceLocationFlags);
void SetSpace(XrAction action, XrPosef pose, XrSpaceLocationFlags spaceLocationFlags);
void SetViewPose(XrViewConfigurationType viewConfigurationType, int viewIndex, XrPosef pose, XrFovf fov);
void SetViewStateFlags(XrViewConfigurationType viewConfigurationType, XrViewStateFlags viewStateFlags);
XrResult GetEndFrameStats(int* primaryLayerCount, int* secondaryLayerCount);
XrResult EndFrame(const XrFrameEndInfo* frameEndInfo);
XrResult CreateActionSet(const XrActionSetCreateInfo* createInfo, XrActionSet* actionSet);
XrResult DestroyActionSet(XrActionSet actionSet);
XrResult CreateAction(XrActionSet actionSet, const XrActionCreateInfo* createInfo, XrAction* action);
XrResult DestroyAction(XrAction action);
XrResult SyncActions(const XrActionsSyncInfo* syncInfo);
XrResult GetActionStateFloat(const XrActionStateGetInfo* getInfo, XrActionStateFloat* state);
XrResult GetActionStateBoolean(const XrActionStateGetInfo* getInfo, XrActionStateBoolean* state);
XrResult GetActionStateVector2f(const XrActionStateGetInfo* getInfo, XrActionStateVector2f* state);
XrResult GetActionStatePose(const XrActionStateGetInfo* getInfo, XrActionStatePose* state);
XrResult CreateReferenceSpace(const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space);
XrResult CreateActionSpace(const XrActionSpaceCreateInfo* createInfo, XrSpace* space);
void VisibilityMaskChangedKHR(XrViewConfigurationType viewConfigurationType, uint32_t viewIndex);
XrResult StringToPath(const char* pathString, XrPath* path);
XrPath StringToPath(const char* pathString);
std::string PathToString(XrPath) const;
XrResult PathToString(XrPath path, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer) const;
// Return the user path portion of the given path handle
XrPath GetUserPath(XrPath path) const
{
return path & 0x00000000FFFFFFFFull;
}
// Return the component path portion of the given path handle
XrPath GetComponentPath(XrPath path) const
{
return path & 0xFFFFFFFF00000000ull;
}
// Make a new path using the given user path and component path
XrPath MakePath(XrPath userPath, XrPath componentPath) const;
// Append the given path
XrPath AppendPath(XrPath path, const char* append);
// Returns true if the given path is a valid path handle
bool IsValidHandle(XrPath path) const;
XrResult GetCurrentInteractionProfile(XrPath topLevelUserPath, XrInteractionProfileState* interactionProfile);
XrResult AttachSessionActionSets(const XrSessionActionSetsAttachInfo* attachInfo);
XrResult SuggestInteractionProfileBindings(const XrInteractionProfileSuggestedBinding* suggestedBindings);
XrResult GetInputSourceLocalizedName(const XrInputSourceLocalizedNameGetInfo* getInfo, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
XrResult LocateViews(const XrViewLocateInfo* viewLocateInfo, XrViewState* viewState, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrView* views);
XrResult EnumerateBoundSourcesForAction(const XrBoundSourcesForActionEnumerateInfo* enumerateInfo, uint32_t sourceCapacityInput, uint32_t* sourceCountOutput, XrPath* sources);
XrResult EnumerateViewConfigurations(XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t* viewConfigurationTypeCountOutput, XrViewConfigurationType* viewConfigurationTypes);
XrResult EnumerateViewConfigurationViews(XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrViewConfigurationView* views);
XrResult EnumerateEnvironmentBlendModes(XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t* environmentBlendModeCountOutput, XrEnvironmentBlendMode* environmentBlendModes);
XrResult ApplyHapticFeedback(const XrHapticActionInfo* hapticActionInfo, const XrHapticBaseHeader* hapticFeedback);
XrResult StopHapticFeedback(const XrHapticActionInfo* hapticActionInfo);
XrResult GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
XrResult ActivateSecondaryView(XrViewConfigurationType viewConfiguration, bool activate);
XrResult RegisterScriptEventCallback(PFN_ScriptEventCallback callback);
XrResult GetSystemProperties(XrSystemId systemId, XrSystemProperties* properties);
XrResult CausePerformanceSettingsNotification(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT nextLevel);
private:
struct MockView
{
XrViewConfigurationView configuration;
XrPosef pose;
XrFovf fov;
};
struct MockViewConfiguration
{
XrViewStateFlags stateFlags;
std::vector<MockView> views;
bool primary;
bool enabled;
bool active;
};
struct MockAction
{
XrAction action;
XrPath path;
std::string name;
std::string localizedName;
XrActionType type;
std::vector<MockInputState*> bindings;
std::vector<XrPath> userPaths;
bool isDestroyed;
};
struct MockActionSet
{
XrActionSet actionSet;
bool attached;
std::string name;
std::string localizedName;
std::vector<MockAction> actions;
bool isDestroyed;
};
struct MockInteractionInputSource
{
XrPath path;
XrActionType actionType;
const char* localizedName;
};
struct MockInteractionProfile
{
XrPath path;
const char* localizedName;
std::vector<XrPath> userPaths;
};
struct MockUserPath
{
std::string path;
std::string localizedName;
const MockInteractionProfile* profile;
};
struct MockSpace
{
XrPosef pose;
bool isDestroyed;
XrAction action;
XrPath subActionPath;
XrSpaceLocationFlags locationFlags;
XrReferenceSpaceType referenceSpaceType;
};
struct MockReferenceSpace
{
bool validExtent;
XrExtent2Df extent;
};
uint64_t GetNextHandle()
{
return ++nextHandle;
}
template <class T>
T GetNextHandle()
{
return (T)GetNextHandle();
}
bool IsValidUserPath(XrPath path) const
{
return path != XR_NULL_PATH && GetUserPath(path) == path;
}
MockActionSet* GetMockActionSet(XrActionSet actionSet);
MockActionSet* GetMockActionSet(XrAction action);
MockAction* GetMockAction(XrAction action);
const MockInteractionProfile* GetMockInteractionProfile(XrPath interactionProfile) const;
bool IsActionAttached(XrAction action);
MockInputState* GetMockInputState(const MockInteractionProfile& mockProfile, XrPath path, XrActionType actionType = XR_ACTION_TYPE_MAX_ENUM);
MockSpace* GetMockSpace(XrSpace space);
MockViewConfiguration* GetMockViewConfiguration(XrViewConfigurationType viewConfigType);
MockView* GetMockView(XrViewConfigurationType viewConfigType, size_t viewIndex);
MockUserPath* GetMockUserPath(XrPath path);
MockReferenceSpace* GetMockReferenceSpace(XrReferenceSpaceType referenceSpaceType);
XrResult ValidateName(const char* name) const;
XrResult ValidatePath(const char* path) const;
XrTime GetPredictedTime();
void InitializeInteractionProfiles();
bool SetActiveInteractionProfile(MockUserPath* mockUserPath, const MockInteractionProfile* mockProfile);
MockInputState* AddMockInputState(XrPath interactionPath, XrPath path, XrActionType actionType, const char* localizedName);
//// XR_MSFT_secondary_view_configuration
XrResult MSFTSecondaryViewConfiguration_BeginSession(const XrSessionBeginInfo* beginInfo);
XrResult MSFTSecondaryViewConfiguration_WaitFrame(const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState);
XrResult MSFTSecondaryViewConfiguration_EndFrame(const XrFrameEndInfo* frameEndInfo);
template <typename T>
void QueueEvent(const T& event)
{
QueueEvent((const XrEventDataBuffer&)event);
}
void QueueEvent(const XrEventDataBuffer& buffer);
XrEventDataBuffer GetNextEvent();
std::vector<XrSecondaryViewConfigurationStateMSFT> secondaryViewConfigurationStates;
//// XR_MSFT_first_person_observer
XrResult MSFTFirstPersonObserver_Init();
//// XR_MSFT_first_person_observer
XrResult MSFTThirdPersonObserver_Init();
std::vector<MockInteractionProfile> interactionProfiles;
MockRuntimeCreateFlags createFlags;
std::queue<XrEventDataBuffer> eventQueue;
XrInstance instance;
XrSession session;
XrSessionState currentState;
XrEnvironmentBlendMode blendMode{XR_ENVIRONMENT_BLEND_MODE_OPAQUE};
bool isRunning;
bool exitSessionRequested;
bool actionSetsAttached;
XrTime lastWaitFrame;
XrTime invalidTimeThreshold;
std::map<XrViewConfigurationType, MockViewConfiguration> viewConfigurations;
XrViewConfigurationType primaryViewConfiguration;
std::vector<std::string> componentPathStrings;
std::vector<MockUserPath> userPaths;
std::chrono::time_point<std::chrono::high_resolution_clock> startTime;
bool instanceIsLost;
bool nullGfx;
int primaryLayersRendered;
int secondaryLayersRendered;
uint64_t nextHandle;
std::vector<MockActionSet> actionSets;
std::vector<MockInputState> inputStates;
std::vector<MockSpace> spaces;
std::map<XrReferenceSpaceType, MockReferenceSpace> referenceSpaces;
PFN_ScriptEventCallback scriptEventCallback;
};
extern MockRuntime* s_runtime;

View File

@@ -0,0 +1,570 @@
#include "mock.h"
struct MockInputSourcePath
{
const char* path;
XrActionType type;
const char* localizedName;
};
struct MockInteractionProfileDef
{
const char* localizedName;
const char* name;
MockRuntimeCreateFlags requiredFlags;
std::vector<const char*> userPaths;
std::vector<MockInputSourcePath> inputSources;
};
static std::vector<MockInteractionProfileDef> s_InteractionProfiles = {
// Mock Controller
{
"Mock Controller",
"/interaction_profiles/unity/mock_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Button"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/thumbstick/value", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Button"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/thumbstick/value", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
}},
// KHR Simple controller
{
"KHR Simple Controller",
"/interaction_profiles/khr/simple_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{{"/user/hand/left/input/select/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Select"},
{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/select/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Select"},
{"/user/hand/right/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"}}},
// Microsoft Mixed Reality Motion Controller Profile
{
"Mixed Reality Controller",
"/interaction_profiles/microsoft/motion_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/squeeze/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Squeeze"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/left/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/left/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/left/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/left/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/right/input/squeeze/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Squeeze"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/right/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/right/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/right/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/right/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"}}},
// Google Daydream Controller Profile
{
"Daydream Controller",
"/interaction_profiles/google/daydream_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{{"/user/hand/left/input/select/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Select"},
{"/user/hand/left/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/left/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/left/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/left/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/left/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Pose"},
{"/user/hand/right/input/select/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Select"},
{"/user/hand/right/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/right/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/right/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/right/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/right/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"}}},
// HTC Vive Controller Profile
{
"HTC Vive Controller",
"/interaction_profiles/htc/vive_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/left/input/squeeze/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Squeeze"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Click"},
{"/user/hand/left/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/left/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/left/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/left/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/left/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/right/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/right/input/squeeze/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Squeeze"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Click"},
{"/user/hand/right/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/right/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/right/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/right/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/right/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"}}},
// HTC Vive Pro Profile
{
"HTC Vive Pro Controller",
"/interaction_profiles/htc/vive_pro",
0,
{"/user/head"},
{
{"/user/head/input/volume_up/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Volume Up"},
{"/user/head/input/volume_down/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Volume Down"},
{"/user/head/input/mute_mic/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Mute Mic"},
}},
// Microsoft Xbox Controller Profile
{
"XBox Controller",
"/interaction_profiles/microsoft/xbox_controller",
0,
{"/user/gamepad"},
{{"/user/gamepad/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/gamepad/input/view/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "View"},
{"/user/gamepad/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/gamepad/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/gamepad/input/x/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "X"},
{"/user/gamepad/input/y/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y"},
{"/user/gamepad/input/dpad_down/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "D-pad Down"},
{"/user/gamepad/input/dpad_right/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "D-pad Right"},
{"/user/gamepad/input/dpad_up/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "D-pad Up"},
{"/user/gamepad/input/dpad_left/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "D-pad Left"},
{"/user/gamepad/input/shoulder_left/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Left Shoulder"},
{"/user/gamepad/input/shoulder_right/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Right Shoulder"},
{"/user/gamepad/input/thumbstick_left/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Left Thumbstick Click"},
{"/user/gamepad/input/thumbstick_right/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Right Thumbstick Click"},
{"/user/gamepad/input/trigger_left/value", XR_ACTION_TYPE_FLOAT_INPUT, "Left Trigger"},
{"/user/gamepad/input/trigger_right/value", XR_ACTION_TYPE_FLOAT_INPUT, "Right Trigger"},
{"/user/gamepad/input/thumbstick_left/x", XR_ACTION_TYPE_FLOAT_INPUT, "Left Thumbstick X"},
{"/user/gamepad/input/thumbstick_left/y", XR_ACTION_TYPE_FLOAT_INPUT, "Left Thumbstick Y"},
{"/user/gamepad/input/thumbstick_left", XR_ACTION_TYPE_VECTOR2F_INPUT, "Left Thumbstick"},
{"/user/gamepad/input/thumbstick_right/x", XR_ACTION_TYPE_FLOAT_INPUT, "Right Thumbstick X"},
{"/user/gamepad/input/thumbstick_right/y", XR_ACTION_TYPE_FLOAT_INPUT, "Right Thumbstick Y"},
{"/user/gamepad/input/thumbstick_right", XR_ACTION_TYPE_VECTOR2F_INPUT, "Right Thumbstick"},
{"/user/gamepad/output/haptic_left", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Left Hatic"},
{"/user/gamepad/output/haptic_right", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Right Haptic"},
{"/user/gamepad/output/haptic_left_trigger", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Left Trigger Haptic"},
{"/user/gamepad/output/haptic_right_trigger", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Right Trigger Haptic"}}},
// Oculus Go Controller Profile
{
"Oculus Go Controller",
"/interaction_profiles/oculus/go_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger"},
{"/user/hand/left/input/back/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Back"},
{"/user/hand/left/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/left/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/left/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/left/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/left/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger"},
{"/user/hand/right/input/back/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Back"},
{"/user/hand/right/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/right/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/right/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/right/input/trackpad/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Click"},
{"/user/hand/right/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Pose"},
}},
// Oculus Touch Controller Profile
{
"Oculus Touch Controller",
"/interaction_profiles/oculus/touch_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/x/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "X"},
{"/user/hand/left/input/x/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "X Touch"},
{"/user/hand/left/input/y/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y"},
{"/user/hand/left/input/y/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y Touch"},
{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Touch"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
// Rift S and Quest controllers lack thumbrests
{"/user/hand/left/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/right/input/a/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "A Touch"},
{"/user/hand/right/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/right/input/b/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "B Touch"},
// The system ("Oculus") button is reserved for system applications
{"/user/hand/right/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Touch"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
// Rift S and Quest controllers lack thumbrests
{"/user/hand/right/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
}},
// Valve Index Controller Profile
{
"Index Controller",
"/interaction_profiles/valve/index_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/left/input/system/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "System Touch"},
{"/user/hand/left/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/left/input/a/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "A Touch"},
{"/user/hand/left/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/left/input/b/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "B Touch"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze"},
{"/user/hand/left/input/squeeze/force", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze Force"},
{"/user/hand/left/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Click"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Touch"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/left/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/left/input/trackpad/force", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Force"},
{"/user/hand/left/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/left/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/right/input/system/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "System Touch"},
{"/user/hand/right/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/right/input/a/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "A Touch"},
{"/user/hand/right/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/right/input/b/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "B Touch"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze"},
{"/user/hand/right/input/squeeze/force", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze Force"},
{"/user/hand/right/input/trigger/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Click"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Touch"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/trackpad/x", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad X"},
{"/user/hand/right/input/trackpad/y", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Y"},
{"/user/hand/right/input/trackpad/force", XR_ACTION_TYPE_FLOAT_INPUT, "Trackpad Force"},
{"/user/hand/right/input/trackpad/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trackpad Touch"},
{"/user/hand/right/input/trackpad", XR_ACTION_TYPE_VECTOR2F_INPUT, "Trackpad"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
}},
// Eye gaze interaction extension
{
"Eye Gaze",
"/interaction_profiles/ext/eye_gaze_interaction",
MR_CREATE_EYE_GAZE_INTERACTION_EXT,
{"/user/eyes_ext"},
{{"/user/eyes_ext/input/gaze_ext/pose", XR_ACTION_TYPE_POSE_INPUT, "Gaze"}}},
// MSFT Hand Interaction extension
{
"Hand",
"/interaction_profiles/microsoft/hand_interaction",
MR_CREATE_MSFT_HAND_INTERACTION_EXT,
{"/user/hand/left", "/user/hand/right"},
{{"/user/hand/left/input/select/value", XR_ACTION_TYPE_FLOAT_INPUT, "Select"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/select/value", XR_ACTION_TYPE_FLOAT_INPUT, "Select"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Squeeze"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"}}},
// Hand Interaction extension
{
"Hand Interaction",
"/interaction_profiles/ext/hand_interaction_ext",
MR_CREATE_HAND_INTERACTION_EXT,
{"/user/hand/left", "/user/hand/right"},
{
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/poke_ext/pose", XR_ACTION_TYPE_POSE_INPUT, "Poke"},
{"/user/hand/left/input/pinch_ext/pose", XR_ACTION_TYPE_POSE_INPUT, "Pinch"},
{"/user/hand/left/input/pinch_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Pinch Value"},
{"/user/hand/left/input/pinch_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Pinch Ready"},
{"/user/hand/left/input/aim_activate_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Pointer Activate Value"},
{"/user/hand/left/input/aim_activate_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Pointer Activate Ready"},
{"/user/hand/left/input/grasp_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grasp Value"},
{"/user/hand/left/input/grasp_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Grasp Ready"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/poke_ext/pose", XR_ACTION_TYPE_POSE_INPUT, "Poke"},
{"/user/hand/right/input/pinch_ext/pose", XR_ACTION_TYPE_POSE_INPUT, "Pinch"},
{"/user/hand/right/input/pinch_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Pinch Value"},
{"/user/hand/right/input/pinch_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Pinch Ready"},
{"/user/hand/right/input/aim_activate_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Pointer Activate Value"},
{"/user/hand/right/input/aim_activate_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Pointer Activate Ready"},
{"/user/hand/right/input/grasp_ext/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grasp Value"},
{"/user/hand/right/input/grasp_ext/ready_ext", XR_ACTION_TYPE_BOOLEAN_INPUT, "Grasp Ready"},
}},
// Meta Quest Pro Touch Controller Profile
{
"Quest Pro Touch Controller",
"/interaction_profiles/facebook/touch_controller_pro",
MR_CREATE_FB_TOUCH_CONTROLLER_PRO,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/x/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "X"},
{"/user/hand/left/input/x/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "X Touch"},
{"/user/hand/left/input/y/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y"},
{"/user/hand/left/input/y/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y Touch"},
{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Touch"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbrest Touch"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/left/input/thumbrest/force", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbrest Force"},
{"/user/hand/left/input/stylus_fb/force", XR_ACTION_TYPE_FLOAT_INPUT, "Stylus Force"},
{"/user/hand/left/input/trigger/curl_fb", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Curl"},
{"/user/hand/left/input/trigger/slide_fb", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Slide"},
{"/user/hand/left/input/trigger/proximity_fb", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Proximity"},
{"/user/hand/left/input/thumb_fb/proximity_fb", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumb Proximity"},
{"/user/hand/left/output/trigger_haptic_fb", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic Trigger"},
{"/user/hand/left/output/thumb_haptic_fb", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic Thumb"},
{"/user/hand/right/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/right/input/a/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "A Touch"},
{"/user/hand/right/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/right/input/b/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "B Touch"},
// The system ("Oculus") button is reserved for system applications
{"/user/hand/right/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Touch"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbrest Touch"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/thumbrest/force", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbrest Force"},
{"/user/hand/right/input/stylus_fb/force", XR_ACTION_TYPE_FLOAT_INPUT, "Stylus Force"},
{"/user/hand/right/input/trigger/curl_fb", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Curl"},
{"/user/hand/right/input/trigger/slide_fb", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Slide"},
{"/user/hand/right/input/trigger/proximity_fb", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Proximity"},
{"/user/hand/right/input/thumb_fb/proximity_fb", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumb Proximity"},
{"/user/hand/right/output/trigger_haptic_fb", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic Trigger"},
{"/user/hand/right/output/thumb_haptic_fb", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic Thumb"},
}},
// HP Reverb G2 Controller Profile
{
"HP Reverb G2 Controller",
"/interaction_profiles/hp/mixed_reality_controller",
0,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/x/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "X"},
{"/user/hand/left/input/y/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y"},
{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/right/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/right/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
}},
// Touch Controller Plus Profile
{
"Meta Quest Touch Plus Controller",
"/interaction_profiles/meta/touch_controller_plus",
MR_CREATE_META_TOUCH_CONTROLLER_PLUS,
{"/user/hand/left",
"/user/hand/right"},
{
{"/user/hand/left/input/x/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "X"},
{"/user/hand/left/input/x/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "X Touch"},
{"/user/hand/left/input/y/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y"},
{"/user/hand/left/input/y/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Y Touch"},
{"/user/hand/left/input/menu/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Menu"},
{"/user/hand/left/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/left/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/left/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Touch"},
{"/user/hand/left/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/left/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/left/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/left/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/left/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/left/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbrest Touch"},
{"/user/hand/left/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/left/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/left/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/left/input/thumb_meta/proximity_meta", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumb Proximity"},
{"/user/hand/left/input/trigger/proximity_meta", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Proximity"},
{"/user/hand/left/input/trigger/curl_meta", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Curl"},
{"/user/hand/left/input/trigger/slide_meta", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Slide"},
{"/user/hand/left/input/trigger/force", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Force"},
{"/user/hand/right/input/a/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "A"},
{"/user/hand/right/input/a/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "A Touch"},
{"/user/hand/right/input/b/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "B"},
{"/user/hand/right/input/b/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "B Touch"},
// The system ("Oculus") button is reserved for system applications
{"/user/hand/right/input/system/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "System"},
{"/user/hand/right/input/squeeze/value", XR_ACTION_TYPE_FLOAT_INPUT, "Grip"},
{"/user/hand/right/input/trigger/value", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger"},
{"/user/hand/right/input/trigger/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Touch"},
{"/user/hand/right/input/thumbstick/x", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick X"},
{"/user/hand/right/input/thumbstick/y", XR_ACTION_TYPE_FLOAT_INPUT, "Thumbstick Y"},
{"/user/hand/right/input/thumbstick/click", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Click"},
{"/user/hand/right/input/thumbstick/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbstick Touch"},
{"/user/hand/right/input/thumbstick", XR_ACTION_TYPE_VECTOR2F_INPUT, "Thumbstick"},
{"/user/hand/right/input/thumbrest/touch", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumbrest Touch"},
{"/user/hand/right/input/grip/pose", XR_ACTION_TYPE_POSE_INPUT, "Grip"},
{"/user/hand/right/input/aim/pose", XR_ACTION_TYPE_POSE_INPUT, "Aim"},
{"/user/hand/right/output/haptic", XR_ACTION_TYPE_VIBRATION_OUTPUT, "Haptic"},
{"/user/hand/right/input/thumb_meta/proximity_meta", XR_ACTION_TYPE_BOOLEAN_INPUT, "Thumb Proximity"},
{"/user/hand/right/input/trigger/proximity_meta", XR_ACTION_TYPE_BOOLEAN_INPUT, "Trigger Proximity"},
{"/user/hand/right/input/trigger/curl_meta", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Curl"},
{"/user/hand/right/input/trigger/slide_meta", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Slide"},
{"/user/hand/right/input/trigger/force", XR_ACTION_TYPE_FLOAT_INPUT, "Trigger Force"},
}}};
void MockRuntime::InitializeInteractionProfiles()
{
inputStates.clear();
interactionProfiles.reserve(s_InteractionProfiles.size());
for (MockInteractionProfileDef& def : s_InteractionProfiles)
{
// Require specific create flags to use this profile?
if ((def.requiredFlags & createFlags) != def.requiredFlags)
continue;
interactionProfiles.emplace_back();
MockInteractionProfile& mockProfile = interactionProfiles.back();
mockProfile.path = StringToPath(def.name);
mockProfile.userPaths.reserve(def.userPaths.size());
mockProfile.localizedName = def.localizedName;
for (const char* userPathString : def.userPaths)
{
mockProfile.userPaths.push_back(StringToPath(userPathString));
}
for (MockInputSourcePath& componentDef : def.inputSources)
{
AddMockInputState(mockProfile.path, StringToPath(componentDef.path), componentDef.type, componentDef.localizedName);
}
}
}
const MockRuntime::MockInteractionProfile* MockRuntime::GetMockInteractionProfile(XrPath interactionProfile) const
{
for (const MockInteractionProfile& mockProfile : interactionProfiles)
if (mockProfile.path == interactionProfile)
return &mockProfile;
return nullptr;
}

View File

@@ -0,0 +1,91 @@
#include "openxr/openxr.h"
// This data was dumped from oculus quest 2.
uint32_t s_VisibilityMaskVerticesSizes[2][3] =
{
// first view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
52,
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
49,
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
48,
},
// second view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
52,
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
49,
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
48,
}};
uint32_t s_VisibilityMaskIndicesSizes[2][3] =
{
// first view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
156,
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
144,
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
48,
},
// second view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
156,
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
144,
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
48,
}};
// clang-format off
XrVector2f s_VisibilityMaskVertices[2][3][99] =
{
// first view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
{ { 1.01f, 1.12253f }, { 1.01f, -1.20286f }, { -1.29274f, -1.20286f }, { -1.29274f, 1.12253f }, { 0.0f, 1.11061f }, { 0.156813f, 1.10997f }, { 0.308857f, 1.07153f }, { 0.460177f, 1.02982f }, { 0.607778f, 0.971561f }, { 0.742182f, 0.886089f }, { 0.848528f, 0.767387f }, { 0.922751f, 0.626911f }, { 0.974118f, 0.481266f }, { 1.0f, 0.335506f }, { 1.0f, 0.192824f }, { 1.0f, 0.0543102f }, { 1.0f, -0.081141f }, { 1.0f, -0.216879f }, { 1.0f, -0.356927f }, { 1.0f, -0.502332f }, { 0.986307f, -0.650586f }, { 0.931474f, -0.795886f }, { 0.848528f, -0.929669f }, { 0.731909f, -1.03498f }, { 0.590278f, -1.10353f }, { 0.439847f, -1.14302f }, { 0.29074f, -1.1662f }, { 0.1458f, -1.1886f }, { -1.19209e-07f, -1.19175f }, { -0.156797f, -1.19175f }, { -0.327742f, -1.19175f }, { -0.510643f, -1.19175f }, { -0.699907f, -1.19175f }, { -0.886918f, -1.19175f }, { -1.06066f, -1.1418f }, { -1.19912f, -1.00126f }, { -1.27994f, -0.82503f }, { -1.27994f, -0.63388f }, { -1.27994f, -0.442625f }, { -1.27994f, -0.258665f }, { -1.27994f, -0.081141f }, { -1.27994f, 0.0980905f }, { -1.27994f, 0.285711f }, { -1.27994f, 0.481404f }, { -1.27994f, 0.677933f }, { -1.22896f, 0.861876f }, { -1.09602f, 1.01487f }, { -0.926783f, 1.11061f }, { -0.739629f, 1.11061f }, { -0.545324f, 1.11061f }, { -0.353049f, 1.11061f }, { -0.169805f, 1.11061f } }, // 52
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
{ { 0.0f, -0.081141f }, { 0.0f, 1.11061f }, { 0.156813f, 1.10997f }, { 0.308857f, 1.07153f }, { 0.460177f, 1.02982f }, { 0.607778f, 0.971561f }, { 0.742182f, 0.886089f }, { 0.848528f, 0.767387f }, { 0.922751f, 0.626911f }, { 0.974118f, 0.481266f }, { 1.0f, 0.335506f }, { 1.0f, 0.192824f }, { 1.0f, 0.0543102f }, { 1.0f, -0.081141f }, { 1.0f, -0.216879f }, { 1.0f, -0.356927f }, { 1.0f, -0.502332f }, { 0.986307f, -0.650586f }, { 0.931474f, -0.795886f }, { 0.848528f, -0.929669f }, { 0.731909f, -1.03498f }, { 0.590278f, -1.10353f }, { 0.439847f, -1.14302f }, { 0.29074f, -1.1662f }, { 0.1458f, -1.1886f }, { -1.19209e-07f, -1.19175f }, { -0.156797f, -1.19175f }, { -0.327742f, -1.19175f }, { -0.510643f, -1.19175f }, { -0.699907f, -1.19175f }, { -0.886918f, -1.19175f }, { -1.06066f, -1.1418f }, { -1.19912f, -1.00126f }, { -1.27994f, -0.82503f }, { -1.27994f, -0.63388f }, { -1.27994f, -0.442625f }, { -1.27994f, -0.258665f }, { -1.27994f, -0.081141f }, { -1.27994f, 0.0980905f }, { -1.27994f, 0.285711f }, { -1.27994f, 0.481404f }, { -1.27994f, 0.677933f }, { -1.22896f, 0.861876f }, { -1.09602f, 1.01487f }, { -0.926783f, 1.11061f }, { -0.739629f, 1.11061f }, { -0.545324f, 1.11061f }, { -0.353049f, 1.11061f }, { -0.169805f, 1.11061f } }, // 49
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
{ { 0.0f, 1.11061f }, { 0.156813f, 1.10997f }, { 0.308857f, 1.07153f }, { 0.460177f, 1.02982f }, { 0.607778f, 0.971561f }, { 0.742182f, 0.886089f }, { 0.848528f, 0.767387f }, { 0.922751f, 0.626911f }, { 0.974118f, 0.481266f }, { 1.0f, 0.335506f }, { 1.0f, 0.192824f }, { 1.0f, 0.0543102f }, { 1.0f, -0.081141f }, { 1.0f, -0.216879f }, { 1.0f, -0.356927f }, { 1.0f, -0.502332f }, { 0.986307f, -0.650586f }, { 0.931474f, -0.795886f }, { 0.848528f, -0.929669f }, { 0.731909f, -1.03498f }, { 0.590278f, -1.10353f }, { 0.439847f, -1.14302f }, { 0.29074f, -1.1662f }, { 0.1458f, -1.1886f }, { -1.19209e-07f, -1.19175f }, { -0.156797f, -1.19175f }, { -0.327742f, -1.19175f }, { -0.510643f, -1.19175f }, { -0.699907f, -1.19175f }, { -0.886918f, -1.19175f }, { -1.06066f, -1.1418f }, { -1.19912f, -1.00126f }, { -1.27994f, -0.82503f }, { -1.27994f, -0.63388f }, { -1.27994f, -0.442625f }, { -1.27994f, -0.258665f }, { -1.27994f, -0.081141f }, { -1.27994f, 0.0980905f }, { -1.27994f, 0.285711f }, { -1.27994f, 0.481404f }, { -1.27994f, 0.677933f }, { -1.22896f, 0.861876f }, { -1.09602f, 1.01487f }, { -0.926783f, 1.11061f }, { -0.739629f, 1.11061f }, { -0.545324f, 1.11061f }, { -0.353049f, 1.11061f }, { -0.169805f, 1.11061f } }, // 48
},
// second view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
{ { -1.01f, 1.12253f }, { -1.01f, -1.20286f }, { 1.29274f, -1.20286f }, { 1.29274f, 1.12253f }, { 0.0f, 1.11061f }, { -0.156813f, 1.10997f }, { -0.308857f, 1.07153f }, { -0.460177f, 1.02982f }, { -0.607778f, 0.971561f }, { -0.742182f, 0.886089f }, { -0.848528f, 0.767387f }, { -0.922751f, 0.626911f }, { -0.974118f, 0.481266f }, { -1.0f, 0.335506f }, { -1.0f, 0.192824f }, { -1.0f, 0.0543102f }, { -1.0f, -0.081141f }, { -1.0f, -0.216879f }, { -1.0f, -0.356927f }, { -1.0f, -0.502332f }, { -0.986307f, -0.650586f }, { -0.931474f, -0.795886f }, { -0.848528f, -0.929669f }, { -0.731909f, -1.03498f }, { -0.590278f, -1.10353f }, { -0.439847f, -1.14302f }, { -0.29074f, -1.1662f }, { -0.1458f, -1.1886f }, { 0.0f, -1.19175f }, { 0.156797f, -1.19175f }, { 0.327742f, -1.19175f }, { 0.510643f, -1.19175f }, { 0.699907f, -1.19175f }, { 0.886918f, -1.19175f }, { 1.06066f, -1.1418f }, { 1.19912f, -1.00126f }, { 1.27994f, -0.82503f }, { 1.27994f, -0.63388f }, { 1.27994f, -0.442625f }, { 1.27994f, -0.258665f }, { 1.27994f, -0.081141f }, { 1.27994f, 0.0980905f }, { 1.27994f, 0.285711f }, { 1.27994f, 0.481404f }, { 1.27994f, 0.677933f }, { 1.22896f, 0.861876f }, { 1.09602f, 1.01487f }, { 0.926783f, 1.11061f }, { 0.739629f, 1.11061f }, { 0.545324f, 1.11061f }, { 0.353049f, 1.11061f }, { 0.169805f, 1.11061f } }, // 52
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
{ { 0.0f, -0.081141f }, { 0.0f, 1.11061f }, { -0.156813f, 1.10997f }, { -0.308857f, 1.07153f }, { -0.460177f, 1.02982f }, { -0.607778f, 0.971561f }, { -0.742182f, 0.886089f }, { -0.848528f, 0.767387f }, { -0.922751f, 0.626911f }, { -0.974118f, 0.481266f }, { -1.0f, 0.335506f }, { -1.0f, 0.192824f }, { -1.0f, 0.0543102f }, { -1.0f, -0.081141f }, { -1.0f, -0.216879f }, { -1.0f, -0.356927f }, { -1.0f, -0.502332f }, { -0.986307f, -0.650586f }, { -0.931474f, -0.795886f }, { -0.848528f, -0.929669f }, { -0.731909f, -1.03498f }, { -0.590278f, -1.10353f }, { -0.439847f, -1.14302f }, { -0.29074f, -1.1662f }, { -0.1458f, -1.1886f }, { 0.0f, -1.19175f }, { 0.156797f, -1.19175f }, { 0.327742f, -1.19175f }, { 0.510643f, -1.19175f }, { 0.699907f, -1.19175f }, { 0.886918f, -1.19175f }, { 1.06066f, -1.1418f }, { 1.19912f, -1.00126f }, { 1.27994f, -0.82503f }, { 1.27994f, -0.63388f }, { 1.27994f, -0.442625f }, { 1.27994f, -0.258665f }, { 1.27994f, -0.081141f }, { 1.27994f, 0.0980905f }, { 1.27994f, 0.285711f }, { 1.27994f, 0.481404f }, { 1.27994f, 0.677933f }, { 1.22896f, 0.861876f }, { 1.09602f, 1.01487f }, { 0.926783f, 1.11061f }, { 0.739629f, 1.11061f }, { 0.545324f, 1.11061f }, { 0.353049f, 1.11061f }, { 0.169805f, 1.11061f } }, // 49
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
{ { 0.00000000f, 1.11061263f }, { -0.156812787f, 1.10997009f }, { -0.308857441f, 1.07153058f }, { -0.460176885f, 1.02982426f }, { -0.607777834f, 0.971561193f }, { -0.742181718f, 0.886089087f }, { -0.848528206f, 0.767387271f }, { -0.922750771f, 0.626910567f }, { -0.974118292f, 0.481266260f }, { -1.00000000f, 0.335505605f }, { -1.00000000f, 0.192823887f }, { -1.00000000f, 0.0543102026f }, { -1.00000000f, -0.0811409950f }, { -1.00000000f, -0.216879249f }, { -1.00000000f, -0.356927097f }, { -1.00000000f, -0.502331913f }, { -0.986306727f, -0.650585532f }, { -0.931473970f, -0.795886219f }, { -0.848528206f, -0.929669261f }, { -0.731908858f, -1.03498316f }, { -0.590277910f, -1.10353208f }, { -0.439846814f, -1.14302492f }, { -0.290739954f, -1.16619778f }, { -0.145799756f, -1.18859875f }, { 0.00000000f, -1.19175363f }, { 0.156797290f, -1.19175363f }, { 0.327741623f, -1.19175363f }, { 0.510643244f, -1.19175363f }, { 0.699907303f, -1.19175363f }, { 0.886917710f, -1.19175363f }, { 1.06066012f, -1.14180124f }, { 1.19912076f, -1.00125873f }, { 1.27994156f, -0.825029850f }, { 1.27994156f, -0.633879662f }, { 1.27994156f, -0.442624867f }, { 1.27994156f, -0.258665323f }, { 1.27994156f, -0.0811409950f }, { 1.27994156f, 0.0980905294f }, { 1.27994156f, 0.285711050f }, { 1.27994156f, 0.481403828f }, { 1.27994156f, 0.677932978f }, { 1.22896290f, 0.861875772f }, { 1.09601569f, 1.01487422f }, { 0.926782608f, 1.11061263f }, { 0.739629149f, 1.11061263f }, { 0.545323849f, 1.11061263f }, { 0.353048563f, 1.11061263f }, { 0.169804931f, 1.11061263f } }, // 48
}
};
uint32_t s_VisibilityMaskIndices[2][3][200] =
{
// first view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
{ 4, 0, 3, 16, 1, 0, 28, 2, 1, 40, 3, 2, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16, 1, 16, 17, 1, 17, 18, 1, 18, 19, 1, 19, 20, 1, 20, 21, 1, 21, 22, 1, 22, 23, 1, 23, 24, 1, 24, 25, 1, 25, 26, 1, 26, 27, 1, 27, 28, 2, 28, 29, 2, 29, 30, 2, 30, 31, 2, 31, 32, 2, 32, 33, 2, 33, 34, 2, 34, 35, 2, 35, 36, 2, 36, 37, 2, 37, 38, 2, 38, 39, 2, 39, 40, 3, 40, 41, 3, 41, 42, 3, 42, 43, 3, 43, 44, 3, 44, 45, 3, 45, 46, 3, 46, 47, 3, 47, 48, 3, 48, 49, 3, 49, 50, 3, 50, 51, 3, 51, 4 }, // 156
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
{ 1, 0, 2, 2, 0, 3, 3, 0, 4, 4, 0, 5, 5, 0, 6, 6, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, 10, 10, 0, 11, 11, 0, 12, 12, 0, 13, 13, 0, 14, 14, 0, 15, 15, 0, 16, 16, 0, 17, 17, 0, 18, 18, 0, 19, 19, 0, 20, 20, 0, 21, 21, 0, 22, 22, 0, 23, 23, 0, 24, 24, 0, 25, 25, 0, 26, 26, 0, 27, 27, 0, 28, 28, 0, 29, 29, 0, 30, 30, 0, 31, 31, 0, 32, 32, 0, 33, 33, 0, 34, 34, 0, 35, 35, 0, 36, 36, 0, 37, 37, 0, 38, 38, 0, 39, 39, 0, 40, 40, 0, 41, 41, 0, 42, 42, 0, 43, 43, 0, 44, 44, 0, 45, 45, 0, 46, 46, 0, 47, 47, 0, 48, 48, 0, 1 }, // 144
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
{ 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, // 48
},
// second view
{
// XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR
{ 0, 4, 3, 1, 16, 0, 2, 28, 1, 3, 40, 2, 4, 0, 5, 5, 0, 6, 6, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, 10, 10, 0, 11, 11, 0, 12, 12, 0, 13, 13, 0, 14, 14, 0, 15, 15, 0, 16, 16, 1, 17, 17, 1, 18, 18, 1, 19, 19, 1, 20, 20, 1, 21, 21, 1, 22, 22, 1, 23, 23, 1, 24, 24, 1, 25, 25, 1, 26, 26, 1, 27, 27, 1, 28, 28, 2, 29, 29, 2, 30, 30, 2, 31, 31, 2, 32, 32, 2, 33, 33, 2, 34, 34, 2, 35, 35, 2, 36, 36, 2, 37, 37, 2, 38, 38, 2, 39, 39, 2, 40, 40, 3, 41, 41, 3, 42, 42, 3, 43, 43, 3, 44, 44, 3, 45, 45, 3, 46, 46, 3, 47, 47, 3, 48, 48, 3, 49, 49, 3, 50, 50, 3, 51, 51, 3, 4 }, // 156
// XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR
{ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10, 0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16, 0, 16, 17, 0, 17, 18, 0, 18, 19, 0, 19, 20, 0, 20, 21, 0, 21, 22, 0, 22, 23, 0, 23, 24, 0, 24, 25, 0, 25, 26, 0, 26, 27, 0, 27, 28, 0, 28, 29, 0, 29, 30, 0, 30, 31, 0, 31, 32, 0, 32, 33, 0, 33, 34, 0, 34, 35, 0, 35, 36, 0, 36, 37, 0, 37, 38, 0, 38, 39, 0, 39, 40, 0, 40, 41, 0, 41, 42, 0, 42, 43, 0, 43, 44, 0, 44, 45, 0, 45, 46, 0, 46, 47, 0, 47, 48, 0, 48, 1 }, // 144
// XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR
{ 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, // 48
}
};

View File

@@ -0,0 +1,69 @@
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // !WIN32_LEAN_AND_MEAN
#include <d3d11.h>
#include <d3d12.h>
#include <windows.h>
#endif
#ifdef XR_USE_PLATFORM_ANDROID
#include <jni.h>
#endif
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#endif
#include <vulkan/vulkan.h>
#define XR_NO_PROTOTYPES
#include "XR/IUnityXRTrace.h"
#include "openxr/openxr.h"
#include "openxr/openxr_platform.h"
#include "plugin_load.h"
#include <openxr/loader_interfaces.h>
#include <openxr/openxr_reflection.h>
struct IUnityXRTrace;
extern IUnityXRTrace* s_Trace;
IUnityXRTrace* s_Trace = nullptr;
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
PluginHandle s_PluginHandle = nullptr;
PFN_xrGetInstanceProcAddr s_GetInstanceProcAddr = nullptr;
static bool LoadMockRuntime()
{
if (nullptr != s_GetInstanceProcAddr)
return true;
s_PluginHandle = Plugin_LoadLibrary(L"mock_runtime");
if (nullptr == s_PluginHandle)
return false;
s_GetInstanceProcAddr = (PFN_xrGetInstanceProcAddr)Plugin_GetSymbol(s_PluginHandle, "xrGetInstanceProcAddr");
return nullptr != s_GetInstanceProcAddr;
}
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function)
{
if (!LoadMockRuntime())
return XR_ERROR_RUNTIME_FAILURE;
return s_GetInstanceProcAddr(instance, name, function);
}
extern "C" void UNITY_INTERFACE_EXPORT XRAPI_PTR SetXRTrace(IUnityXRTrace* trace)
{
if (!LoadMockRuntime())
return;
typedef void (*PFN_SetXRTrace)(IUnityXRTrace * trace);
PFN_SetXRTrace set = (PFN_SetXRTrace)Plugin_GetSymbol(s_PluginHandle, "SetXRTrace");
if (set != nullptr)
set(trace);
}

View File

@@ -0,0 +1,29 @@
# Mock Runtime 0.0.2
OpenXR Runtime that allows for testing without a device.
## Paths
The `XrPath` handles generated by the Mock Runtime are a combination of two identifiers with the high 32-bits being the component path and the low 32-bits being the user path. This allows for quick comparisons of portions of the path and isolates the parsing of the path to the `xrStringToPath` method. The `GetUserPath` and `GetComponentPath` methods can be used to extract the individual parts of the `XrPath`.
## Interaction Profiles
The list of all interaction profiles supported by the mock runtime can be found in `mock_runtime_interaction_profiles.cpp`. This list is 1.0 conformant and will be used to create a list of `MockInteractionProfile` instances in the Mock Runtime as well as generate the list of all [Input State](#input-state) instances.
## Action Sets
Action sets within the Mock Runtime are stored in a list within the runtime state. The `XrActionSet` handle returned from `CreateActionSet` contains the index of the action set into the action set list. To convert a `XrActionSet` handle into a `MockActionSet` use the `GetMockActionSet` method within the runtime.
## Actions
The Mock Runtime implements conformant action support. Since the Mock Runtime does not have any actual controllers it will instead mimic the first interaction profile it receives through suggested bindings. This means that no actions will have bindings until bindings are suggested and that `xrGetCurrentInteractionProfile` will return the first interaction profile encountered by `xrSuggestInteractionProfileBindings`. When `xrSuggestInteractionProfileBindings` is called the actions are bound to known [Input State](#input-state) which allows those values to be directly controlled via the conformance automation extension.
The `XrAction` handle generated by `CreateAction` is a combination of the action set index (low 32-bits) that the action belongs to and the action index within the parent action set (high 32-bits). Since actions are stored as children of an action set this handle format allows an action to be found quickly without any indirect lookups. The methods `GetMockActionSet` and `GetMockAction` will convert an `XrAction` handle in to an `MockActionSet` and `MockAction` respectively.
## Input State
The MockRuntime manages a list of input states, one for each combination of interaction profile, user path, and input source path. These input states have an `XrActionType` to define the type of data they represent, which is defined by their interaction profile. This allows the Mock Runtime to allow binding to any input source on any known interaction profile. However this does mean that there may be multiple instances of a input source (ex. `/input/grip` may exist multiple times, for each interaction profile). The side effect of this design is that if you bind multiple interaction profiles to the same action then there will be two sources of data for that action and the [OpenXR Specification](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#multiple_inputs) on how to resolve which to use will be applied.
## Conformance Automation Extension
The MockRuntime implements the conformance automation extension and allows [Input State](#input-state) values to be set. When a value is set via Conformance Automation it is temporarly stored in the extension itself rather than directly settings the equivalent value in Mock Runtime. The values stored in the extension will then be read by the MockRuntime during `xrSyncActions` and copied into the runtime state where they will persist.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5315f44a895de4c4e8bfe5cb24317219
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
{
"name": "Unity.XR.OpenXR.Features.MockRuntime",
"references": [
"Unity.XR.OpenXR",
"Unity.XR.OpenXR.Editor",
"Unity.InputSystem"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
""
],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6150739e4dc7bff4d833306fd9d5a4f0
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7caf1a202b3e406b947ab5a8f6043dcd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 332de653f55c454c89a23c5dc5cc042c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: fba69233fcf54ad5914ccf4e2ed55030
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: ARM64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: f8baebd7864440598dc9dbb51194580d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: ARM64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: 2537db8455274393a170604e47774283
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: ARM64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b109cbbf65634ef595bba2527417fbdb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: e27e85025e9c4a9482dbd4e357c1806e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: X86_64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: 29baad48fb434237a5cf4c2418cdfe78
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: X86_64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,82 @@
fileFormatVersion: 2
guid: 9d61b882d40c42e68f33ace157ffdacd
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: X86_64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c6205b2956ab42969b748112a4a5d613
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Packages/com.unity.xr.openxr/MockRuntime/osx/mock_api.dylib (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: fefd9e05a6e945bd8a999aa366de7ce1
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: OSX
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: 7b4d53bfe77e40209965d1577977674c
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: OSX
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: b616ed3500ce4fd9a114d188119c288a
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: OSX
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
{
"file_format_version": "1.0.0",
"runtime":
{
"api_version": "1.0",
"name": "Unity Mock Runtime",
"library_path": ".\\windows\\x64\\mock_runtime.dll"
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f4c90870f0f8d764da1dda3fb931630d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 775d4c50d229402faed528c1d26eb1a3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fad624da6b254ca7a8be5b4aac094dc2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,81 @@
fileFormatVersion: 2
guid: 3b9265782fe34c5c87551ca60e45b595
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
Exclude WindowsStoreApps: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: Windows
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
DontProcess: false
PlaceholderPath:
SDK: AnySDK
ScriptingBackend: AnyScriptingBackend
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,81 @@
fileFormatVersion: 2
guid: d20b3852da9b4a51804a72ed6ef2b3a8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
Exclude WindowsStoreApps: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: Windows
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
DontProcess: false
PlaceholderPath:
SDK: AnySDK
ScriptingBackend: AnyScriptingBackend
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,81 @@
fileFormatVersion: 2
guid: e9d41955cc5a4810b59c81e5d543168e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
Exclude WindowsStoreApps: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: Windows
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
DontProcess: false
PlaceholderPath:
SDK: AnySDK
ScriptingBackend: AnyScriptingBackend
userData:
assetBundleName:
assetBundleVariant: