上传YomovSDK
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__CYGWIN32__)
|
||||
#define UNITY_INTERFACE_API __stdcall
|
||||
#define UNITY_INTERFACE_EXPORT __declspec(dllexport)
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)
|
||||
#define UNITY_INTERFACE_API __stdcall
|
||||
#define UNITY_INTERFACE_EXPORT __declspec(dllexport)
|
||||
#elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) || defined(LUMIN)
|
||||
#define UNITY_INTERFACE_API
|
||||
#define UNITY_INTERFACE_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define UNITY_INTERFACE_API
|
||||
#define UNITY_INTERFACE_EXPORT
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
||||
@@ -0,0 +1,485 @@
|
||||
diff --git a/specification/scripts/creflectiongenerator.py b/specification/scripts/creflectiongenerator.py
|
||||
index a1beca84a..fa08160ee 100644
|
||||
--- a/specification/scripts/creflectiongenerator.py
|
||||
+++ b/specification/scripts/creflectiongenerator.py
|
||||
@@ -35,11 +35,13 @@ class CommandData:
|
||||
class StructData:
|
||||
"""Represents a OpenXR struct type"""
|
||||
|
||||
- def __init__(self, typeName, structTypeName, members, protect):
|
||||
+ def __init__(self, typeName, structTypeName, members, arrays, protect, parent):
|
||||
self.typeName = typeName
|
||||
self.members = members
|
||||
+ self.arrays = arrays
|
||||
self.structTypeName = structTypeName
|
||||
self.protect = protect
|
||||
+ self.parent = parent
|
||||
|
||||
@property
|
||||
def protect_value(self) -> bool:
|
||||
@@ -64,12 +66,42 @@ class BitmaskData:
|
||||
class EnumData:
|
||||
"""Represents a OpenXR group enum type"""
|
||||
|
||||
- def __init__(self, typeName, typeNamePrefix, typeNameSuffix, enumTuples):
|
||||
+ def __init__(self, typeName, typeNamePrefix, typeNameSuffix, enumTuples, protect):
|
||||
self.typeName = typeName
|
||||
self.typeNamePrefix = typeNamePrefix
|
||||
self.typeNameSuffix = typeNameSuffix
|
||||
self.enumTuples = enumTuples
|
||||
+ self.protect = protect
|
||||
+
|
||||
+ @property
|
||||
+ def protect_value(self):
|
||||
+ return self.protect is not None
|
||||
+
|
||||
+ @property
|
||||
+ def protect_string(self):
|
||||
+ if self.protect:
|
||||
+ return " && ".join("defined({})".format(x) for x in self.protect)
|
||||
+
|
||||
+class CCmd:
|
||||
+ """Represents an OpenXR function"""
|
||||
+
|
||||
+ def __init__(self, cmdName, returnType, members, members_non_array, arrays, sig, protect):
|
||||
+ self.cmdName = cmdName
|
||||
+ self.returnType = returnType
|
||||
+ self.members = members
|
||||
+ self.members_non_array = members_non_array
|
||||
+ self.arrays = arrays
|
||||
+ self.sig = sig
|
||||
+ self.protect = protect
|
||||
+
|
||||
+ @property
|
||||
+ def protect_value(self):
|
||||
+ return self.protect is not None
|
||||
|
||||
+ @property
|
||||
+ def protect_string(self):
|
||||
+ if self.protect:
|
||||
+ return " && ".join("defined({})".format(x) for x in self.protect)
|
||||
|
||||
class CReflectionOutputGenerator(OutputGenerator):
|
||||
"""Generate specified API interfaces in a specific style, such as a C header"""
|
||||
@@ -81,6 +113,8 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
self.commands = []
|
||||
self.enums = []
|
||||
self.bitmasks = []
|
||||
+ self.cmds = []
|
||||
+ self.handles = []
|
||||
self.protects = set()
|
||||
self.template: Optional[JinjaTemplate] = None
|
||||
self.parents = {}
|
||||
@@ -97,14 +131,42 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
if x.protect == protect and x.structTypeName is not None]
|
||||
return ret
|
||||
|
||||
+ def getCmdsForProtect(self, protect=None):
|
||||
+ return [x for x in self.cmds
|
||||
+ if x.protect == protect]
|
||||
+
|
||||
+ def getEnumsForProtect(self, protect=None):
|
||||
+ return [x for x in self.enums
|
||||
+ if x.protect == protect]
|
||||
+
|
||||
+ def getCmdsForProtect(self, protect=None):
|
||||
+ return [x for x in self.cmds
|
||||
+ if x.protect == protect]
|
||||
+
|
||||
+ def getEnumsForProtect(self, protect=None):
|
||||
+ return [x for x in self.enums
|
||||
+ if x.protect == protect]
|
||||
+
|
||||
def endFile(self):
|
||||
assert self.template
|
||||
assert self.registry
|
||||
file_data = ''
|
||||
|
||||
+ # UNITY: specialization filter
|
||||
+ self.cmds = [x for x in self.cmds if x.cmdName not in ('xrGetInstanceProcAddr')]
|
||||
+ self.structs = [x for x in self.structs if x.typeName not in ('XrBaseInStructure', 'XrBaseOutStructure', 'XrEventDataBuffer', 'XrDebugUtilsMessengerCreateInfoEXT', 'XrSpatialGraphNodeSpaceCreateInfoMSFT', 'XrInteractionProfileAnalogThresholdVALVE', 'XrWorldMeshBufferML')]
|
||||
+
|
||||
unprotected_structs = self._get_structs_for_protect()
|
||||
protected_structs = [(x, self._get_structs_for_protect(protect=x))
|
||||
for x in sorted(self.protects)]
|
||||
+ base_structs = list(set([x.parent for x in self.structs if x.parent is not None]))
|
||||
+ basic_structs = [x for x in self.structs if x.structTypeName is None and x.typeName not in base_structs]
|
||||
+
|
||||
+ unprotected_cmds = self.getCmdsForProtect()
|
||||
+ protected_cmds = [(x, self.getCmdsForProtect(x)) for x in sorted(self.protects)]
|
||||
+
|
||||
+ unprotected_enums = self.getEnumsForProtect()
|
||||
+ protected_enums = [(x, self.getEnumsForProtect(x)) for x in sorted(self.protects)]
|
||||
# drop empty collections
|
||||
protected_structs = [(x, y) for x, y in protected_structs if y]
|
||||
|
||||
@@ -138,7 +200,15 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
unprotectedStructs=unprotected_structs,
|
||||
protectedStructs=protected_structs,
|
||||
structs=self.structs,
|
||||
+ basic_structs=basic_structs,
|
||||
+ base_structs=base_structs,
|
||||
+ unprotectedCmds=unprotected_cmds,
|
||||
+ protectedCmds=protected_cmds,
|
||||
+ cmds=self.cmds,
|
||||
+ unprotectedEnums=unprotected_enums,
|
||||
+ protectedEnums=protected_enums,
|
||||
enums=self.enums,
|
||||
+ handles=self.handles,
|
||||
bitmasks=self.bitmasks,
|
||||
extensions=extensions,
|
||||
polymorphic_struct_families=polymorphic_struct_families,
|
||||
@@ -159,6 +229,8 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
# If the type is a struct type, generate it using the
|
||||
# special-purpose generator.
|
||||
self.genStruct(typeinfo, name, alias)
|
||||
+ if category == 'handle':
|
||||
+ self.handles.append(name)
|
||||
|
||||
parent_struct = typeElem.get('parentstruct')
|
||||
if parent_struct is not None:
|
||||
@@ -174,12 +246,75 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
|
||||
self.commands.append(CommandData(name, self.featureName))
|
||||
|
||||
+ def genCmd(self, cmd, cmdinfo, alias):
|
||||
+ OutputGenerator.genCmd(self, cmd, cmdinfo, alias)
|
||||
+
|
||||
+ if alias:
|
||||
+ return
|
||||
+
|
||||
+ #print(f'{dump(cmd.elem)}')
|
||||
+
|
||||
+ ret = cmd.elem.find('proto').find('type').text
|
||||
+ #print(ret)
|
||||
+
|
||||
+ members = []
|
||||
+ members_non_array = []
|
||||
+ sig = ''
|
||||
+
|
||||
+
|
||||
+ arrays = {}
|
||||
+ for m in cmd.elem.findall('./param[@len]'):
|
||||
+ lenName = m.get('len')
|
||||
+ if lenName != 'null-terminated':
|
||||
+ if m.find('type').text == 'char' and 'null-terminated' not in lenName:
|
||||
+ continue
|
||||
+ lenName = lenName.replace(',null-terminated','')
|
||||
+ print(f"{m.find('name').text} len={lenName}")
|
||||
+ arrays[m.find('name').text] = lenName
|
||||
+
|
||||
+ for m in cmd.elem.iterfind('param'):
|
||||
+ sig += ', ' + self.makeCParamDecl(m, 0)
|
||||
+ member = m.find('name').text
|
||||
+ members.append(m.find('name').text)
|
||||
+ if member not in arrays:
|
||||
+ members_non_array.append(m.find('name').text)
|
||||
+
|
||||
+ sig = sig[2:]
|
||||
+
|
||||
+ #import pprint
|
||||
+ #pprint.pprint(members)
|
||||
+
|
||||
+ protect = set()
|
||||
+ if self.featureExtraProtect:
|
||||
+ protect.update(self.featureExtraProtect.split(','))
|
||||
+ localProtect = cmd.elem.get('protect')
|
||||
+ if localProtect:
|
||||
+ protect.update(localProtect.split(','))
|
||||
+
|
||||
+ if protect:
|
||||
+ protect = tuple(protect)
|
||||
+ else:
|
||||
+ protect = None
|
||||
+
|
||||
+ self.cmds.append(CCmd(cmd.elem.attrib['name'], ret, members, members_non_array, arrays, sig, protect))
|
||||
+
|
||||
+
|
||||
def genStruct(self, typeinfo, typeName, alias):
|
||||
OutputGenerator.genStruct(self, typeinfo, typeName, alias)
|
||||
|
||||
if alias:
|
||||
return
|
||||
|
||||
+ arrays = {}
|
||||
+ for m in typeinfo.elem.findall('./member[@len]'):
|
||||
+ lenName = m.get('len')
|
||||
+ if lenName != 'null-terminated':
|
||||
+ if m.find('type').text == 'char' and 'null-terminated' not in lenName:
|
||||
+ continue
|
||||
+ lenName = lenName.replace(',null-terminated','')
|
||||
+ print(f"{m.find('name').text} len={lenName}")
|
||||
+ arrays[m.find('name').text] = lenName
|
||||
+
|
||||
structTypeEnum = None
|
||||
members = []
|
||||
for member in typeinfo.getMembers():
|
||||
@@ -188,7 +323,8 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
if self.conventions.is_structure_type_member(memberType, memberName):
|
||||
structTypeEnum = member.get("values")
|
||||
|
||||
- members.append(memberName)
|
||||
+ if memberName not in arrays:
|
||||
+ members.append(memberName)
|
||||
|
||||
protect = set()
|
||||
if self.featureExtraProtect:
|
||||
@@ -202,7 +338,9 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
else:
|
||||
protect = None
|
||||
|
||||
- self.structs.append(StructData(typeName, structTypeEnum, members, protect))
|
||||
+ parent = typeinfo.elem.get('parentstruct')
|
||||
+
|
||||
+ self.structs.append(StructData(typeName, structTypeEnum, members, arrays, protect, parent))
|
||||
if protect:
|
||||
self.protects.add(protect)
|
||||
|
||||
@@ -242,4 +380,16 @@ class CReflectionOutputGenerator(OutputGenerator):
|
||||
continue
|
||||
enumTuples.append((getElemName(elem), strVal))
|
||||
|
||||
- self.enums.append(EnumData(groupName, expandPrefix, expandSuffix, enumTuples))
|
||||
+ protect = set()
|
||||
+ if self.featureExtraProtect:
|
||||
+ protect.update(self.featureExtraProtect.split(','))
|
||||
+ localProtect = groupinfo.elem.get('protect')
|
||||
+ if localProtect:
|
||||
+ protect.update(localProtect.split(','))
|
||||
+
|
||||
+ if protect:
|
||||
+ protect = tuple(protect)
|
||||
+ else:
|
||||
+ protect = None
|
||||
+
|
||||
+ self.enums.append(EnumData(groupName, expandPrefix, expandSuffix, enumTuples, protect))
|
||||
diff --git a/specification/scripts/template_openxr_reflection.h b/specification/scripts/template_openxr_reflection.h
|
||||
index 11ec318d1..9ddbbc8e1 100644
|
||||
--- a/specification/scripts/template_openxr_reflection.h
|
||||
+++ b/specification/scripts/template_openxr_reflection.h
|
||||
@@ -12,7 +12,7 @@
|
||||
**
|
||||
*/
|
||||
|
||||
-#include "openxr.h"
|
||||
+// #include "openxr.h"
|
||||
|
||||
/*
|
||||
This file contains expansion macros (X Macros) for OpenXR enumerations and structures.
|
||||
@@ -30,6 +30,13 @@ Example of how to use expansion macros to make an enum-to-string function:
|
||||
XR_ENUM_STR(XrResult);
|
||||
*/
|
||||
|
||||
+#define XR_LIST_HANDLES(_) \
|
||||
+//# for handle in handles
|
||||
+ _(/*{handle}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
//# for enum in enums
|
||||
|
||||
#define XR_LIST_ENUM_/*{enum.typeName}*/(_) \
|
||||
@@ -40,6 +47,39 @@ XR_ENUM_STR(XrResult);
|
||||
|
||||
//# endfor
|
||||
|
||||
+//## Used when making structure type macros
|
||||
+/*% macro makeEnumTypes(typedEnums) -%*/
|
||||
+//# for enum in typedEnums
|
||||
+ _(/*{enum.typeName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+/*% endmacro %*/
|
||||
+
|
||||
+#define XR_LIST_ENUM_TYPES_CORE(_) \
|
||||
+/*{ makeEnumTypes(unprotectedEnums) }*/
|
||||
+
|
||||
+
|
||||
+//# for protect, enumTypes in protectedEnums if enumTypes|length > 0
|
||||
+
|
||||
+/*{ protect_begin(enumTypes[0]) }*/
|
||||
+#define XR_LIST_ENUM_TYPES_/*{protect | join("_")}*/(_) \
|
||||
+/*{ makeEnumTypes(enumTypes) }*/
|
||||
+#else
|
||||
+#define XR_LIST_ENUM_TYPES_/*{protect | join("_")}*/(_)
|
||||
+#endif
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+
|
||||
+#define XR_LIST_ENUM_TYPES(_) \
|
||||
+ XR_LIST_ENUM_TYPES_CORE(_) \
|
||||
+//# for protect, enumTypes in protectedEnums if enumTypes|length > 0
|
||||
+ XR_LIST_ENUM_TYPES_/*{protect | join("_")}*/(_) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
//# for bitmask in bitmasks
|
||||
|
||||
#define XR_LIST_BITS_/*{bitmask.typeName}*/(_)/*{" \\" if bitmask.maskTuples}*/
|
||||
@@ -61,6 +101,16 @@ XR_ENUM_STR(XrResult);
|
||||
//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
//# endfor
|
||||
|
||||
+//# for struct in structs
|
||||
+
|
||||
+#define XR_LIST_STRUCT_ARRAYS_/*{struct.typeName}*/(_) \
|
||||
+//# for memberName, lenName in struct.arrays.items()
|
||||
+ _(/*{memberName}*/, /*{lenName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+//# endfor
|
||||
+
|
||||
//## Used when making structure type macros
|
||||
/*% macro makeStructTypes(typedStructs, funcName="_") -%*/
|
||||
//# for struct in typedStructs
|
||||
@@ -98,6 +148,62 @@ XR_ENUM_STR(XrResult);
|
||||
//# endfor
|
||||
|
||||
|
||||
+
|
||||
+#define XR_LIST_BASE_STRUCTS(_) \
|
||||
+//# for structTypeName in base_structs
|
||||
+ _(/*{structTypeName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# for structName in base_structs
|
||||
+
|
||||
+#define XR_LIST_BASE_STRUCT_TYPES_CORE_/*{structName}*/(_) \
|
||||
+//# for struct in unprotectedStructs if struct.parent == structName
|
||||
+ _(/*{struct.typeName}*/, /*{struct.structTypeName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# for protect, structTypes in protectedStructs
|
||||
+/*{ protect_begin(structTypes[0]) }*/
|
||||
+#define XR_LIST_BASE_STRUCT_TYPES_/*{structName}*/_/*{protect | join("_")}*/(_) \
|
||||
+//# for struct in structTypes if struct.parent == structName
|
||||
+ _(/*{struct.typeName}*/, /*{struct.structTypeName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+#else
|
||||
+#define XR_LIST_BASE_STRUCT_TYPES_/*{structName}*/_/*{protect | join("_")}*/(_)
|
||||
+#endif
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+#define XR_LIST_BASE_STRUCT_TYPES_/*{structName}*/(_) \
|
||||
+ XR_LIST_BASE_STRUCT_TYPES_CORE_/*{structName}*/(_) \
|
||||
+//# for protect, structTypes in protectedStructs
|
||||
+ XR_LIST_BASE_STRUCT_TYPES_/*{structName}*/_/*{protect | join("_")}*/(_) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+
|
||||
+
|
||||
+#define XR_LIST_BASIC_STRUCTS(_) \
|
||||
+//# for s in basic_structs
|
||||
+ _(/*{s.typeName}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+
|
||||
//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
|
||||
/// Calls your macro with the name and extension number of all known
|
||||
@@ -126,4 +232,82 @@ XR_ENUM_STR(XrResult);
|
||||
|
||||
//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
|
||||
+
|
||||
+//## Used when making cmd type macros
|
||||
+/*% macro makeCmdTypes(cmds) -%*/
|
||||
+//# for cmd in cmds
|
||||
+ _(/*{cmd.cmdName}*/, /*{cmd.sig}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+/*% endmacro %*/
|
||||
+
|
||||
+#define XR_LIST_FUNCS_CORE(_) \
|
||||
+/*{ makeCmdTypes(unprotectedCmds) }*/
|
||||
+
|
||||
+
|
||||
+//# for protect, cmdTypes in protectedCmds if cmdTypes|length > 0
|
||||
+
|
||||
+/*{ protect_begin(cmdTypes[0]) }*/
|
||||
+#define XR_LIST_FUNCS_/*{protect | join("_")}*/(_) \
|
||||
+/*{ makeCmdTypes(cmdTypes) }*/
|
||||
+#else
|
||||
+#define XR_LIST_FUNCS_/*{protect | join("_")}*/(_)
|
||||
+#endif
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+
|
||||
+#define XR_LIST_FUNCS(_) \
|
||||
+ XR_LIST_FUNCS_CORE(_) \
|
||||
+//# for protect, cmdTypes in protectedCmds if cmdTypes|length > 0
|
||||
+ XR_LIST_FUNCS_/*{protect | join("_")}*/(_) \
|
||||
+//# endfor
|
||||
+
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# for cmd in cmds
|
||||
+
|
||||
+#define XR_LIST_FUNC_/*{cmd.cmdName}*/(_) \
|
||||
+//# for member in cmd.members_non_array
|
||||
+ _(/*{member}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+//# for cmd in cmds
|
||||
+
|
||||
+#define XR_LIST_FUNC_ARRAYS_/*{cmd.cmdName}*/(_) \
|
||||
+//# for member, len_member in cmd.arrays.items()
|
||||
+ _(/*{member}*/, /*{len_member}*/) \
|
||||
+//# endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+//# for cmd in cmds
|
||||
+
|
||||
+#define XR_LIST_FUNC_PARAM_NAMES_/*{cmd.cmdName}*/(_) \
|
||||
+ _(/*{', '.join(cmd.members)}*/) \
|
||||
+
|
||||
+//## Preceding line intentionally left blank to absorb the trailing backslash
|
||||
+
|
||||
+//# endfor
|
||||
+
|
||||
+//# for cmd in cmds
|
||||
+#define XR_BEFORE_/*{cmd.cmdName}*/(funcName)
|
||||
+//#endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank
|
||||
+
|
||||
+//# for cmd in cmds
|
||||
+#define XR_AFTER_/*{cmd.cmdName}*/(funcName)
|
||||
+//#endfor
|
||||
+
|
||||
+//## Preceding line intentionally left blank
|
||||
+
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
#include <jni.h>
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||
#include <d3d11_4.h>
|
||||
#endif
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||
#include <d3d12.h>
|
||||
#endif
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||
#if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB)
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
#ifdef XR_USE_PLATFORM_XCB
|
||||
#include <xcb/glx.h>
|
||||
#endif
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
#include <GL/gl.h>
|
||||
#include <wingdi.h> // For HGLRC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#endif
|
||||
#if defined(XR_USE_PLATFORM_ANDROID) && !defined(XR_USE_UNITY)
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
@@ -0,0 +1,585 @@
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// Block-based dynamic allocator via ring-buffer.
|
||||
// Ring buffer that stores "blocks" which dynamically grow and wrap.
|
||||
// If a section grows large enough that it overlaps another section, the other section is forgotten.
|
||||
// 8 bit alignment, bring your own synchronization.
|
||||
// Must call Create first, and Destroy when done. Must create a section before writing.
|
||||
// This probably isn't perfect.. some tests are at the bottom and it seems to be stable for the usecase.
|
||||
struct RingBuf
|
||||
{
|
||||
enum OverflowMode
|
||||
{
|
||||
kOverflowModeWrap,
|
||||
kOverflowModeTruncate,
|
||||
kOverflowModeGrowDouble,
|
||||
};
|
||||
|
||||
uint8_t* data;
|
||||
uint32_t cacheSize;
|
||||
OverflowMode overflowMode;
|
||||
|
||||
// must be pointer because of thread_local compiler bug
|
||||
std::deque<uint32_t>* offsets;
|
||||
|
||||
void Create(uint32_t csize, OverflowMode overflowMode)
|
||||
{
|
||||
this->overflowMode = overflowMode;
|
||||
if (data == nullptr)
|
||||
{
|
||||
data = (uint8_t*)malloc(csize);
|
||||
cacheSize = csize;
|
||||
offsets = new std::deque<uint32_t>();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
void SetOverflowMode(OverflowMode overflowMode)
|
||||
{
|
||||
this->overflowMode = overflowMode;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (offsets != nullptr)
|
||||
{
|
||||
offsets->clear();
|
||||
offsets->push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
if (data != nullptr)
|
||||
{
|
||||
free(data);
|
||||
data = nullptr;
|
||||
delete (offsets);
|
||||
cacheSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateNewBlock()
|
||||
{
|
||||
if (offsets != nullptr)
|
||||
offsets->push_back(offsets->back());
|
||||
}
|
||||
|
||||
void DropLastBlock()
|
||||
{
|
||||
if (offsets != nullptr)
|
||||
offsets->pop_back();
|
||||
}
|
||||
|
||||
uint8_t* GetForWrite(uint32_t size)
|
||||
{
|
||||
uint8_t* ret{nullptr};
|
||||
|
||||
if (offsets == nullptr)
|
||||
return nullptr;
|
||||
if (size > cacheSize && overflowMode == kOverflowModeWrap)
|
||||
return nullptr;
|
||||
if (offsets->size() < 2)
|
||||
return nullptr;
|
||||
|
||||
uint32_t head = offsets->front();
|
||||
uint32_t tail = offsets->back();
|
||||
offsets->pop_back();
|
||||
|
||||
// need to wrap
|
||||
if (tail + size > cacheSize)
|
||||
{
|
||||
if (overflowMode == kOverflowModeWrap)
|
||||
{
|
||||
// section grew larger than full buffer and overwrote itself, abort.
|
||||
if (offsets->size() == 1)
|
||||
return nullptr;
|
||||
|
||||
if (offsets->back() != tail)
|
||||
offsets->push_back(tail);
|
||||
|
||||
uint32_t front = offsets->front();
|
||||
while (front != 0)
|
||||
{
|
||||
offsets->pop_front();
|
||||
front = offsets->front();
|
||||
}
|
||||
offsets->pop_front();
|
||||
|
||||
offsets->push_back(0);
|
||||
|
||||
head = offsets->front();
|
||||
tail = offsets->back();
|
||||
}
|
||||
else if (overflowMode == kOverflowModeGrowDouble)
|
||||
{
|
||||
while (tail + size > cacheSize)
|
||||
{
|
||||
// grow
|
||||
uint32_t newCacheSize = cacheSize * 2;
|
||||
uint8_t* newData = (uint8_t*)malloc(newCacheSize);
|
||||
memcpy(newData, data, cacheSize);
|
||||
free(data);
|
||||
data = newData;
|
||||
cacheSize = newCacheSize;
|
||||
}
|
||||
}
|
||||
else if (overflowMode == kOverflowModeTruncate)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// need to free space / forget sections
|
||||
if (tail <= head && head != 0)
|
||||
{
|
||||
while (tail + size > head)
|
||||
{
|
||||
offsets->pop_front();
|
||||
|
||||
head = offsets->front();
|
||||
tail = offsets->back();
|
||||
|
||||
if (offsets->size() == 1)
|
||||
break;
|
||||
|
||||
if (*(offsets->begin() + 1) == 0)
|
||||
{
|
||||
offsets->pop_front();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offsets->push_back(tail + size);
|
||||
ret = &data[tail];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HasDataForRead()
|
||||
{
|
||||
return offsets != nullptr && offsets->size() > 1 && offsets[0] != offsets[1];
|
||||
}
|
||||
|
||||
// returns true if there is more data to read
|
||||
// in practice there may be two reads necessary to get all the data, from mid to end and from beginning to mid.
|
||||
// reading is a one time operation - data is cleared after read.
|
||||
bool GetForReadAndClear(uint8_t** ptr, uint32_t* size)
|
||||
{
|
||||
if (offsets == nullptr)
|
||||
{
|
||||
*ptr = nullptr;
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t head = offsets->front();
|
||||
*ptr = &data[head];
|
||||
|
||||
uint32_t max = 0;
|
||||
for (auto it = offsets->begin(); it != offsets->end();)
|
||||
{
|
||||
if (*it > max)
|
||||
max = *it;
|
||||
else if (max == 0)
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
it = offsets->erase(it);
|
||||
}
|
||||
|
||||
*size = max - head;
|
||||
|
||||
return offsets->size() > 1 && size != 0;
|
||||
}
|
||||
|
||||
bool GetForRead(uint8_t** ptr, uint32_t* size)
|
||||
{
|
||||
if (overflowMode == kOverflowModeGrowDouble && offsets != nullptr)
|
||||
{
|
||||
*ptr = data;
|
||||
*size = offsets->back();
|
||||
return false;
|
||||
}
|
||||
*ptr = nullptr;
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MoveFrom(RingBuf& other)
|
||||
{
|
||||
if (other.HasDataForRead() && offsets != nullptr)
|
||||
{
|
||||
CreateNewBlock();
|
||||
uint8_t* ptr{};
|
||||
uint32_t size{};
|
||||
bool more = false;
|
||||
do
|
||||
{
|
||||
more = other.GetForReadAndClear(&ptr, &size);
|
||||
uint8_t* dst = GetForWrite(size);
|
||||
if (dst != nullptr)
|
||||
{
|
||||
memcpy(dst, ptr, size);
|
||||
}
|
||||
} while (more);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Write(Command c)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(Command));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(Command*)wbuf = c;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(LUT l)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(LUT));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(LUT*)wbuf = l;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(std::thread::id id)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << id;
|
||||
Write(ss.str());
|
||||
}
|
||||
|
||||
void Write(const std::string& s)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(char) * ((uint32_t)s.size() + 1));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
memcpy(wbuf, s.c_str(), sizeof(char) * (uint32_t)s.size());
|
||||
wbuf[s.size()] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(float f)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(float));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(float*)wbuf = f;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(int32_t i)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(int32_t));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(int32_t*)wbuf = i;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(int64_t i)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(int64_t));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(int64_t*)wbuf = i;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(uint32_t u)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(uint32_t));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(uint32_t*)wbuf = u;
|
||||
}
|
||||
}
|
||||
|
||||
void Write(uint64_t u)
|
||||
{
|
||||
uint8_t* wbuf = GetForWrite(sizeof(uint64_t));
|
||||
if (wbuf != nullptr)
|
||||
{
|
||||
*(uint64_t*)wbuf = u;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//#define CACHE_SIZE 1024 * 1024 * 1
|
||||
//
|
||||
//int tests()
|
||||
//{
|
||||
// RingBuf buf{};
|
||||
// buf.Create(CACHE_SIZE);
|
||||
//
|
||||
// uint8_t* ptr;
|
||||
// uint32_t size;
|
||||
//
|
||||
// // Check that starts out empty
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 0);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Write
|
||||
// buf.CreateNewBlock();
|
||||
// auto* wbuf = buf.GetForWrite(4);
|
||||
// *(uint32_t*)wbuf = 0x12345678;
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 4);
|
||||
// assert(*(uint32_t*)ptr == 0x12345678);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Write 2
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(4);
|
||||
// *(uint32_t*)wbuf = 0x12345678;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// *(uint64_t*)wbuf = 0x123456789abcdef0;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 12);
|
||||
// assert(*(uint32_t*)ptr == 0x12345678);
|
||||
// assert(*(uint64_t*)(ptr + 4) == 0x123456789abcdef0);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Full buf
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 16);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == CACHE_SIZE);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Wrap buf, perfectly lines up
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 16);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 16); ++i)
|
||||
// wbuf[i] = 3;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 4;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == true);
|
||||
// assert(size == CACHE_SIZE - 8);
|
||||
// assert(ptr[0] == 2);
|
||||
// assert(ptr[8] == 3);
|
||||
// assert(ptr[size - 1] == 3);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 8);
|
||||
// assert(ptr[0] == 4);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Wrap buf, not perfect
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 20);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 20); ++i)
|
||||
// wbuf[i] = 3;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 4;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == true);
|
||||
// assert(size == CACHE_SIZE - 12);
|
||||
// assert(ptr[0] == 2);
|
||||
// assert(ptr[8] == 3);
|
||||
// assert(ptr[size - 1] == 3);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 8);
|
||||
// assert(ptr[0] == 4);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Wrap, and fit more in previous first spot
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 16);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 16); ++i)
|
||||
// wbuf[i] = 3;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(4);
|
||||
// for (int i = 0; i < 4; ++i)
|
||||
// wbuf[i] = 4;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(4);
|
||||
// for (int i = 0; i < 4; ++i)
|
||||
// wbuf[i] = 5;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == true);
|
||||
// assert(size == CACHE_SIZE - 8);
|
||||
// assert(ptr[0] == 2);
|
||||
// assert(ptr[8] == 3);
|
||||
// assert(ptr[size - 1] == 3);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 8);
|
||||
// assert(ptr[0] == 4);
|
||||
// assert(ptr[4] == 5);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Wrap, and consume first two entries
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 16);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 16); ++i)
|
||||
// wbuf[i] = 3;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(4);
|
||||
// for (int i = 0; i < 4; ++i)
|
||||
// wbuf[i] = 4;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 5;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == true);
|
||||
// assert(size == CACHE_SIZE - 8 - 8);
|
||||
// assert(ptr[0] == 3);
|
||||
// assert(ptr[size - 1] == 3);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 12);
|
||||
// assert(ptr[0] == 4);
|
||||
// assert(ptr[4] == 5);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Wrap, and consume first three entries
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 16);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 16); ++i)
|
||||
// wbuf[i] = 3;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(4);
|
||||
// for (int i = 0; i < 4; ++i)
|
||||
// wbuf[i] = 4;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 5;
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 6;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 20);
|
||||
// assert(ptr[0] == 4);
|
||||
// assert(ptr[4] == 5);
|
||||
// assert(ptr[12] == 6);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Section wraps, perfectly
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// buf.GetForWrite(CACHE_SIZE);
|
||||
// for (int i = 0; i < (CACHE_SIZE); ++i)
|
||||
// wbuf[i] = 2;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == CACHE_SIZE);
|
||||
// assert(ptr[0] == 2);
|
||||
// assert(ptr[CACHE_SIZE - 1] == 2);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // Section wraps, not perfect
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 1;
|
||||
// buf.CreateNewBlock();
|
||||
// buf.GetForWrite(CACHE_SIZE - 16);
|
||||
// for (int i = 0; i < (CACHE_SIZE - 16); ++i)
|
||||
// wbuf[i] = 2;
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// for (int i = 0; i < 8; ++i)
|
||||
// wbuf[i] = 2;
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == true);
|
||||
// assert(size == CACHE_SIZE - 8);
|
||||
// assert(ptr[0] == 2);
|
||||
// assert(ptr[size - 1] == 2);
|
||||
//
|
||||
// assert(buf.GetForReadAndClear(&ptr, &size) == false);
|
||||
// assert(size == 8);
|
||||
// assert(ptr[0] == 2);
|
||||
// buf.Reset();
|
||||
//
|
||||
// // section wraps on itself
|
||||
// buf.CreateNewBlock();
|
||||
// wbuf = buf.GetForWrite(CACHE_SIZE - 8);
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
//
|
||||
// wbuf = buf.GetForWrite(8);
|
||||
// assert(wbuf == nullptr);
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "platform_includes.h"
|
||||
|
||||
#include <openxr/openxr_platform_defines.h>
|
||||
|
||||
// 32-bit builds don't have type-safe handles so we can't distinguish them
|
||||
#define XR_TYPE_SAFE_HANDLES (XR_PTR_SIZE == 8)
|
||||
|
||||
#if !defined(XR_DEFINE_ATOM)
|
||||
#if XR_TYPE_SAFE_HANDLES
|
||||
#define XR_DEFINE_ATOM(object) typedef struct object##_T* object;
|
||||
#else
|
||||
#define XR_DEFINE_ATOM(object) typedef uint64_t object;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define XR_NO_PROTOTYPES
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_loader_negotiation.h>
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
#include "openxr/openxr_reflection_full.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
|
||||
#include "api_exports.h"
|
||||
|
||||
#define CATCH_MISSING_TEMPLATES 0
|
||||
|
||||
static void SendString(const char* fieldName, const char* t);
|
||||
|
||||
template <typename T>
|
||||
void SendToCSharp(const char* fieldname, T t)
|
||||
#if !CATCH_MISSING_TEMPLATES
|
||||
{
|
||||
SendString(fieldname, "<Unknown>");
|
||||
}
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
void SendToCSharp(const char* fieldname, T* t)
|
||||
#if !CATCH_MISSING_TEMPLATES
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "0x%p", t);
|
||||
SendString(fieldname, buf);
|
||||
}
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
// Arrays of base structs
|
||||
template <typename structType>
|
||||
bool SendToCSharpBaseStructArray(const char* fieldname, structType t, int lenParam)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nullptrs
|
||||
void SendToCSharpNullPtr(const char* fieldname)
|
||||
{
|
||||
SendString(fieldname, "nullptr");
|
||||
}
|
||||
|
||||
// These includes are order-sensitive
|
||||
// clang-format off
|
||||
#include "serialize_data.h"
|
||||
#include "serialize_data_access.h"
|
||||
|
||||
#include "serialize_primitives.h"
|
||||
#include "serialize_enums.h"
|
||||
#include "serialize_handles.h"
|
||||
#include "serialize_atoms.h"
|
||||
#include "serialize_nextptr.h"
|
||||
#include "serialize_external.h"
|
||||
#include "serialize_structs.h"
|
||||
#include "serialize_todo.h"
|
||||
#include "serialize_nextptr_impl.h"
|
||||
|
||||
#include "serialize_funcs_specialization.h"
|
||||
#include "serialize_funcs.h"
|
||||
// clang-format on
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
StartFunctionCall("xrGetInstanceProcAddr");
|
||||
SendToCSharp("instance", instance);
|
||||
SendToCSharp("name", name);
|
||||
SendToCSharp("function", "<func>");
|
||||
|
||||
XR_LIST_FUNCS(GEN_FUNC_LOAD)
|
||||
|
||||
EndFunctionCall("xrGetInstanceProcAddr", "UNKNOWN FUNC");
|
||||
|
||||
return orig_xrGetInstanceProcAddr(instance, name, function);
|
||||
}
|
||||
|
||||
extern "C" PFN_xrGetInstanceProcAddr UNITY_INTERFACE_EXPORT XRAPI_PTR HookXrInstanceProcAddr(PFN_xrGetInstanceProcAddr func, uint32_t cacheSize, uint32_t perThreadCacheSize)
|
||||
{
|
||||
ResetLUT();
|
||||
s_CacheSize = cacheSize;
|
||||
s_PerThreadCacheSize = perThreadCacheSize;
|
||||
s_MainDataStore.SetOverflowMode(RingBuf::kOverflowModeTruncate);
|
||||
orig_xrGetInstanceProcAddr = func;
|
||||
return xrGetInstanceProcAddr;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#if XR_TYPE_SAFE_HANDLES
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrSystemId t)
|
||||
{
|
||||
SendToCSharp(fieldname, (uint64_t)t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrSystemId* t)
|
||||
{
|
||||
if (t == nullptr)
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
else
|
||||
SendToCSharp(fieldname, (uint64_t)*t);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,314 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
enum Command
|
||||
{
|
||||
kStartFunctionCall,
|
||||
kStartStruct,
|
||||
|
||||
kFloat,
|
||||
kString,
|
||||
kInt32,
|
||||
kInt64,
|
||||
kUInt32,
|
||||
kUInt64,
|
||||
|
||||
kEndStruct,
|
||||
kEndFunctionCall,
|
||||
|
||||
kCacheNotLargeEnough,
|
||||
|
||||
kLUTDefineTables,
|
||||
kLUTEntryUpdateStart,
|
||||
kLutEntryUpdateEnd,
|
||||
kLUTLookup,
|
||||
|
||||
kEndData = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
enum LUT
|
||||
{
|
||||
kXrPath,
|
||||
kXrAction,
|
||||
kXrActionSet,
|
||||
kXrSpace,
|
||||
|
||||
kLUTPadding = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static const char* const kLutNames[] = {
|
||||
"XrPaths",
|
||||
"XrActions",
|
||||
"XrActionSets",
|
||||
"XrSpaces",
|
||||
};
|
||||
|
||||
#include "ringbuf.h"
|
||||
|
||||
static std::mutex s_DataMutex;
|
||||
|
||||
// These get set from c# in HookXrInstanceProcAddr
|
||||
static uint32_t s_CacheSize = 0;
|
||||
static uint32_t s_PerThreadCacheSize = 0;
|
||||
static uint32_t s_LUTCacheSize = 256; // TODO:
|
||||
|
||||
// Accessing this must be protected with s_DataMutex.
|
||||
// Only add into these at kEndFunctionCall to avoid mixing with other threads.
|
||||
static RingBuf s_MainDataStore = {};
|
||||
|
||||
static RingBuf s_LUTDataStore = {};
|
||||
|
||||
// Thread local storage of serialized commands.
|
||||
// On EndFunctionCall they'll be moved into the static storage w/ mutex lock.
|
||||
thread_local RingBuf s_ThreadLocalDataStore = {};
|
||||
|
||||
static void StartFunctionCall(const char* funcName)
|
||||
{
|
||||
if (s_ThreadLocalDataStore.cacheSize != s_PerThreadCacheSize)
|
||||
{
|
||||
s_ThreadLocalDataStore.Destroy();
|
||||
s_ThreadLocalDataStore.Create(s_PerThreadCacheSize, RingBuf::kOverflowModeWrap);
|
||||
}
|
||||
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kStartFunctionCall);
|
||||
s_ThreadLocalDataStore.Write(std::this_thread::get_id());
|
||||
s_ThreadLocalDataStore.Write(funcName);
|
||||
}
|
||||
|
||||
static void StartStruct(const char* fieldName, const char* structName)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kStartStruct);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(structName);
|
||||
}
|
||||
|
||||
static void SendFloat(const char* fieldName, float t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kFloat);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void SendString(const char* fieldName, const char* t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kString);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void SendInt32(const char* fieldName, int32_t t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kInt32);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void SendInt64(const char* fieldName, int64_t t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kInt64);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void SendUInt32(const char* fieldName, uint32_t t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kUInt32);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void SendUInt64(const char* fieldName, uint64_t t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kUInt64);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write(t);
|
||||
}
|
||||
|
||||
static void EndStruct()
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kEndStruct);
|
||||
}
|
||||
|
||||
static void EndFunctionCall(const char* funcName, const char* result)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kEndFunctionCall);
|
||||
s_ThreadLocalDataStore.Write(result);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_DataMutex);
|
||||
|
||||
if (s_MainDataStore.cacheSize != s_CacheSize)
|
||||
{
|
||||
s_MainDataStore.Destroy();
|
||||
s_MainDataStore.Create(s_CacheSize, RingBuf::kOverflowModeTruncate);
|
||||
}
|
||||
|
||||
if (!s_MainDataStore.MoveFrom(s_ThreadLocalDataStore))
|
||||
{
|
||||
s_MainDataStore.CreateNewBlock();
|
||||
s_MainDataStore.Write(kCacheNotLargeEnough);
|
||||
s_MainDataStore.Write(std::this_thread::get_id());
|
||||
s_MainDataStore.Write(funcName);
|
||||
s_MainDataStore.Write(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetLUT()
|
||||
{
|
||||
s_LUTDataStore.Destroy();
|
||||
s_LUTDataStore.Create(s_LUTCacheSize, RingBuf::kOverflowModeGrowDouble);
|
||||
s_LUTDataStore.CreateNewBlock();
|
||||
|
||||
// Setup LUTS
|
||||
s_LUTDataStore.Write(kLUTDefineTables);
|
||||
uint32_t numLuts = (uint32_t)(sizeof(kLutNames) / sizeof(kLutNames[0]));
|
||||
s_LUTDataStore.Write(numLuts);
|
||||
for (uint32_t i = 0; i < numLuts; ++i)
|
||||
{
|
||||
s_LUTDataStore.Write(kLutNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void StoreInLUT(const char* funcName)
|
||||
{
|
||||
if (s_LUTDataStore.cacheSize < s_LUTCacheSize)
|
||||
{
|
||||
ResetLUT();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_DataMutex); // TODO: probably have a different mutex for LUT data store
|
||||
s_LUTDataStore.MoveFrom(s_ThreadLocalDataStore);
|
||||
}
|
||||
|
||||
// We hijacked the function that was already started.
|
||||
// Start a function call for the real call which happens next.
|
||||
StartFunctionCall(funcName);
|
||||
}
|
||||
|
||||
static void SendXrPathCreate(const char* funcName, XrPath path, const char* string)
|
||||
{
|
||||
s_ThreadLocalDataStore.Reset();
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kLUTEntryUpdateStart);
|
||||
s_ThreadLocalDataStore.Write(kXrPath);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)path);
|
||||
s_ThreadLocalDataStore.Write(string);
|
||||
StartStruct("", "");
|
||||
EndStruct();
|
||||
|
||||
StoreInLUT(funcName);
|
||||
}
|
||||
|
||||
static void SendXrPath(const char* fieldName, XrPath t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kLUTLookup);
|
||||
s_ThreadLocalDataStore.Write(kXrPath);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char*, const XrActionCreateInfo*);
|
||||
static void SendXrActionCreate(const char* funcName, XrAction action, const XrActionCreateInfo* createInfo)
|
||||
{
|
||||
s_ThreadLocalDataStore.Reset();
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kLUTEntryUpdateStart);
|
||||
s_ThreadLocalDataStore.Write(kXrAction);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)action);
|
||||
s_ThreadLocalDataStore.Write(createInfo->actionName);
|
||||
SendToCSharp("", createInfo);
|
||||
|
||||
StoreInLUT(funcName);
|
||||
}
|
||||
|
||||
static void SendXrAction(const char* fieldName, XrAction t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kLUTLookup);
|
||||
s_ThreadLocalDataStore.Write(kXrAction);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char*, const XrActionSetCreateInfo*);
|
||||
static void SendXrActionSetCreate(const char* funcName, XrActionSet actionSet, const XrActionSetCreateInfo* createInfo)
|
||||
{
|
||||
s_ThreadLocalDataStore.Reset();
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kLUTEntryUpdateStart);
|
||||
s_ThreadLocalDataStore.Write(kXrActionSet);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)actionSet);
|
||||
s_ThreadLocalDataStore.Write(createInfo->actionSetName);
|
||||
SendToCSharp("", createInfo);
|
||||
|
||||
StoreInLUT(funcName);
|
||||
}
|
||||
|
||||
static void SendXrActionSet(const char* fieldName, XrActionSet t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kLUTLookup);
|
||||
s_ThreadLocalDataStore.Write(kXrActionSet);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char*, const XrActionSpaceCreateInfo*);
|
||||
static void SendXrActionSpaceCreate(const char* funcName, const XrActionSpaceCreateInfo* createInfo, XrSpace* space)
|
||||
{
|
||||
s_ThreadLocalDataStore.Reset();
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kLUTEntryUpdateStart);
|
||||
s_ThreadLocalDataStore.Write(kXrSpace);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)*space);
|
||||
s_ThreadLocalDataStore.Write("Action Space");
|
||||
SendToCSharp("", createInfo);
|
||||
|
||||
StoreInLUT(funcName);
|
||||
}
|
||||
|
||||
#define GENERATE_REFERENCE_SPACE_STRING(enumentry, enumvalue) \
|
||||
case enumvalue: \
|
||||
return #enumentry; \
|
||||
break;
|
||||
|
||||
static const char* GetReferenceSpaceString(XrReferenceSpaceType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
XR_LIST_ENUM_XrReferenceSpaceType(GENERATE_REFERENCE_SPACE_STRING) default : return "Reference Space Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char*, const XrReferenceSpaceCreateInfo*);
|
||||
static void SendXrReferenceSpaceCreate(const char* funcName, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space)
|
||||
{
|
||||
s_ThreadLocalDataStore.Reset();
|
||||
s_ThreadLocalDataStore.CreateNewBlock();
|
||||
s_ThreadLocalDataStore.Write(kLUTEntryUpdateStart);
|
||||
s_ThreadLocalDataStore.Write(kXrSpace);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)*space);
|
||||
s_ThreadLocalDataStore.Write(GetReferenceSpaceString(createInfo->referenceSpaceType));
|
||||
SendToCSharp("", createInfo);
|
||||
|
||||
StoreInLUT(funcName);
|
||||
}
|
||||
|
||||
static void SendXrSpace(const char* fieldName, XrSpace t)
|
||||
{
|
||||
s_ThreadLocalDataStore.Write(kLUTLookup);
|
||||
s_ThreadLocalDataStore.Write(kXrSpace);
|
||||
s_ThreadLocalDataStore.Write(fieldName);
|
||||
s_ThreadLocalDataStore.Write((uint64_t)t);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
extern "C" void UNITY_INTERFACE_EXPORT StartDataAccess()
|
||||
{
|
||||
s_DataMutex.lock();
|
||||
}
|
||||
|
||||
extern "C" bool UNITY_INTERFACE_EXPORT GetDataForRead(uint8_t** ptr, uint32_t* size)
|
||||
{
|
||||
s_MainDataStore.SetOverflowMode(RingBuf::kOverflowModeWrap);
|
||||
return s_MainDataStore.GetForReadAndClear(ptr, size);
|
||||
}
|
||||
|
||||
extern "C" bool UNITY_INTERFACE_EXPORT GetLUTData(uint8_t** ptr, uint32_t* size, uint32_t offset)
|
||||
{
|
||||
bool ret = s_LUTDataStore.GetForRead(ptr, size);
|
||||
if (*size <= offset)
|
||||
{
|
||||
*ptr = nullptr;
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
*ptr = *ptr + offset;
|
||||
*size = *size - offset;
|
||||
s_LUTDataStore.DropLastBlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" void UNITY_INTERFACE_EXPORT EndDataAccess()
|
||||
{
|
||||
s_MainDataStore.Reset();
|
||||
s_DataMutex.unlock();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#define SEND_TO_CSHARP_ENUM_INDIVIDUAL(enumentry, enumvalue) \
|
||||
case enumvalue: \
|
||||
SendToCSharp(fieldname, #enumentry); \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_ENUMS(enumname) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, enumname t) \
|
||||
{ \
|
||||
switch (t) \
|
||||
{ \
|
||||
XR_LIST_ENUM_##enumname(SEND_TO_CSHARP_ENUM_INDIVIDUAL) default : SendToCSharp(fieldname, "UNKNOWN"); \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_LIST_ENUM_TYPES(SEND_TO_CSHARP_ENUMS)
|
||||
|
||||
#define SEND_TO_CSHARP_ENUMS_PTR(enumname) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, enumname* t) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
switch (*t) \
|
||||
{ \
|
||||
XR_LIST_ENUM_##enumname(SEND_TO_CSHARP_ENUM_INDIVIDUAL) default : SendToCSharp(fieldname, "UNKNOWN"); \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_LIST_ENUM_TYPES(SEND_TO_CSHARP_ENUMS_PTR)
|
||||
|
||||
#define XR_ENUM_CASE_STR(name, val) \
|
||||
case name: \
|
||||
return #name;
|
||||
#define XR_ENUM_STR(enumType) \
|
||||
const char* XrEnumStr(enumType e) \
|
||||
{ \
|
||||
switch (e) \
|
||||
{ \
|
||||
XR_LIST_ENUM_##enumType(XR_ENUM_CASE_STR) default : return "Unknown"; \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_ENUM_STR(XrResult);
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#if XR_USE_GRAPHICS_API_D3D11
|
||||
//struct ID3D11Texture2D;
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, LUID t)
|
||||
{
|
||||
StartStruct(fieldname, "LUID");
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "0x%x", t.LowPart);
|
||||
SendToCSharp("LowPart", buf);
|
||||
snprintf(buf, 32, "0x%x", t.HighPart);
|
||||
SendToCSharp("HighPart", buf);
|
||||
EndStruct();
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, D3D_FEATURE_LEVEL t)
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "0x%x", t);
|
||||
SendToCSharp(fieldname, buf);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
// Begin Declaration of original functions
|
||||
static PFN_xrGetInstanceProcAddr orig_xrGetInstanceProcAddr;
|
||||
|
||||
#define GEN_ORIG_FUNC_PTRS(f, ...) \
|
||||
static PFN_##f orig_##f;
|
||||
|
||||
XR_LIST_FUNCS(GEN_ORIG_FUNC_PTRS)
|
||||
// End Declaration of original functions
|
||||
|
||||
#define GEN_PARAMS(...) \
|
||||
__VA_ARGS__
|
||||
|
||||
#define SEND_PARAM_TO_CSHARP(param) \
|
||||
SendToCSharp(#param, param);
|
||||
|
||||
#define SEND_ARRAY_TO_CSHARP(param, lenParam) \
|
||||
if (!SendToCSharpBaseStructArray(#param, param, lenParam)) \
|
||||
{ \
|
||||
for (uint32_t i = 0; i < lenParam; ++i) \
|
||||
SendToCSharp(#param, param[i]); \
|
||||
}
|
||||
|
||||
#define GEN_FUNCS(f, ...) \
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR f(__VA_ARGS__) \
|
||||
{ \
|
||||
XR_BEFORE_##f(#f); \
|
||||
StartFunctionCall(#f); \
|
||||
XrResult result = orig_##f(XR_LIST_FUNC_PARAM_NAMES_##f(GEN_PARAMS)); \
|
||||
XR_AFTER_##f(#f); \
|
||||
uint32_t lastCount = 0; \
|
||||
XR_LIST_FUNC_##f(SEND_PARAM_TO_CSHARP); \
|
||||
XR_LIST_FUNC_ARRAYS_##f(SEND_ARRAY_TO_CSHARP); \
|
||||
EndFunctionCall(#f, XrEnumStr(result)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
XR_LIST_FUNCS(GEN_FUNCS)
|
||||
|
||||
#define GEN_FUNC_LOAD(f, ...) \
|
||||
if (strcmp(#f, name) == 0) \
|
||||
{ \
|
||||
auto ret = orig_xrGetInstanceProcAddr(instance, name, (PFN_xrVoidFunction*)&orig_##f); \
|
||||
if (ret == XR_SUCCESS) \
|
||||
*function = (PFN_xrVoidFunction)&f; \
|
||||
EndFunctionCall(#f, XrEnumStr(ret)); \
|
||||
return ret; \
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
//XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrLoadControllerModelMSFT(XrSession session, XrControllerModelKeyMSFT modelKey, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, uint8_t* buffer)
|
||||
#undef XR_BEFORE_xrLoadControllerModelMSFT
|
||||
#define XR_BEFORE_xrLoadControllerModelMSFT(funcName) \
|
||||
{ \
|
||||
StartFunctionCall(funcName); \
|
||||
XrResult result = orig_xrLoadControllerModelMSFT(session, modelKey, bufferCapacityInput, bufferCountOutput, buffer); \
|
||||
SendToCSharp("session", session); \
|
||||
SendToCSharp("modelKey", modelKey); \
|
||||
SendToCSharp("bufferCapacityInput", bufferCapacityInput); \
|
||||
SendToCSharp("bufferCountOutput", bufferCountOutput); \
|
||||
SendToCSharp("buffer", "<TODO>"); \
|
||||
EndFunctionCall("xrLoadControllerModelMSFT", XrEnumStr(result)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
//XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrStringToPath(XrInstance instance, const char* pathString, XrPath* path)
|
||||
#undef XR_AFTER_xrStringToPath
|
||||
#define XR_AFTER_xrStringToPath(funcName) \
|
||||
{ \
|
||||
/* Cache off path -> string for later lookup .. send it off to c# for UI */ \
|
||||
if (XR_SUCCEEDED(result)) \
|
||||
SendXrPathCreate(funcName, *path, pathString); \
|
||||
}
|
||||
|
||||
//typedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet actionSet, const XrActionCreateInfo* createInfo, XrAction* action);
|
||||
#undef XR_AFTER_xrCreateAction
|
||||
#define XR_AFTER_xrCreateAction(funcName) \
|
||||
{ \
|
||||
if (XR_SUCCEEDED(result)) \
|
||||
SendXrActionCreate(funcName, *action, createInfo); \
|
||||
}
|
||||
|
||||
//typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance instance, const XrActionSetCreateInfo* createInfo, XrActionSet* actionSet);
|
||||
#undef XR_AFTER_xrCreateActionSet
|
||||
#define XR_AFTER_xrCreateActionSet(funcName) \
|
||||
{ \
|
||||
if (XR_SUCCEEDED(result)) \
|
||||
SendXrActionSetCreate(funcName, *actionSet, createInfo); \
|
||||
}
|
||||
|
||||
// typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession session, const XrActionSpaceCreateInfo* createInfo, XrSpace* space);
|
||||
#undef XR_AFTER_xrCreateActionSpace
|
||||
#define XR_AFTER_xrCreateActionSpace(funcName) \
|
||||
{ \
|
||||
if (XR_SUCCEEDED(result)) \
|
||||
SendXrActionSpaceCreate(funcName, createInfo, space); \
|
||||
}
|
||||
|
||||
// typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession session, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space);
|
||||
#undef XR_AFTER_xrCreateReferenceSpace
|
||||
#define XR_AFTER_xrCreateReferenceSpace(funcName) \
|
||||
{ \
|
||||
if (XR_SUCCEEDED(result)) \
|
||||
SendXrReferenceSpaceCreate(funcName, createInfo, space); \
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
// Handles are defined as uin64_t on 32-bit builds. They already have a template defined, so we need to exclude this block from 32-bit builds.
|
||||
// (and remember that _WIN32 is defined on 64-bit windows builds)
|
||||
#if XR_TYPE_SAFE_HANDLES
|
||||
|
||||
typedef struct XrActionSpecialize_t* XrActionSpecialize;
|
||||
#define XrAction XrActionSpecialize
|
||||
typedef struct XrActionSetSpecialize_t* XrActionSetSpecialize;
|
||||
#define XrActionSet XrActionSetSpecialize
|
||||
typedef struct XrSpaceSpecialize_t* XrSpaceSpecialize;
|
||||
#define XrSpace XrSpaceSpecialize
|
||||
|
||||
#define SEND_TO_CSHARP_HANDLES(handlename) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, handlename t) \
|
||||
{ \
|
||||
SendToCSharp(fieldname, (uint64_t)t); \
|
||||
}
|
||||
|
||||
XR_LIST_HANDLES(SEND_TO_CSHARP_HANDLES)
|
||||
|
||||
#define SEND_TO_CSHARP_HANDLES_PTRS(handlename) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, handlename* t) \
|
||||
{ \
|
||||
if (t != nullptr) \
|
||||
SendToCSharp(fieldname, (uint64_t)*t); \
|
||||
else \
|
||||
SendToCSharp(fieldname, (uint64_t)0); \
|
||||
}
|
||||
|
||||
XR_LIST_HANDLES(SEND_TO_CSHARP_HANDLES_PTRS)
|
||||
|
||||
#undef XrAction
|
||||
#undef XrActionSet
|
||||
#undef XrSpace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrBaseOutStructure* t);
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrBaseInStructure const* t);
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, void* t)
|
||||
{
|
||||
if (t != nullptr && strcmp(fieldname, "next") == 0)
|
||||
{
|
||||
SendToCSharp(fieldname, reinterpret_cast<XrBaseOutStructure*>(t));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendToCSharp(fieldname, (uint64_t)t);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, void const* t)
|
||||
{
|
||||
if (t != nullptr && strcmp(fieldname, "next") == 0)
|
||||
{
|
||||
SendToCSharp(fieldname, reinterpret_cast<XrBaseInStructure const*>(t));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendToCSharp(fieldname, (uint64_t)t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#define SEND_NEXT_PTR(structname, structtype) \
|
||||
case structtype: \
|
||||
SendToCSharp("next", reinterpret_cast<structname*>(next)); \
|
||||
break;
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrBaseOutStructure* t)
|
||||
{
|
||||
auto* next = t;
|
||||
do
|
||||
{
|
||||
switch (next->type)
|
||||
{
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_NEXT_PTR)
|
||||
default:
|
||||
SendToCSharp("next", next->type);
|
||||
continue;
|
||||
}
|
||||
} while ((next = static_cast<XrBaseOutStructure*>(next->next)) != nullptr);
|
||||
}
|
||||
|
||||
#define SEND_NEXT_PTR_CONST(structname, structtype) \
|
||||
case structtype: \
|
||||
SendToCSharp("next", reinterpret_cast<structname const*>(next)); \
|
||||
break;
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrBaseInStructure const* t)
|
||||
{
|
||||
auto* next = t;
|
||||
do
|
||||
{
|
||||
switch (next->type)
|
||||
{
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_NEXT_PTR_CONST)
|
||||
default:
|
||||
SendToCSharp("next", next->type);
|
||||
continue;
|
||||
}
|
||||
} while ((next = static_cast<XrBaseInStructure const*>(next->next)) != nullptr);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, int32_t t)
|
||||
{
|
||||
SendInt32(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, int32_t* t)
|
||||
{
|
||||
if (t != nullptr)
|
||||
SendInt32(fieldname, *t);
|
||||
else
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, int64_t t)
|
||||
{
|
||||
SendInt64(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, uint32_t t)
|
||||
{
|
||||
SendUInt32(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, uint32_t* t)
|
||||
{
|
||||
if (t != nullptr)
|
||||
SendUInt32(fieldname, *t);
|
||||
else
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, uint64_t t)
|
||||
{
|
||||
SendUInt64(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, float t)
|
||||
{
|
||||
SendFloat(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, float* t)
|
||||
{
|
||||
if (t != nullptr)
|
||||
SendFloat(fieldname, *t);
|
||||
else
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, char* t)
|
||||
{
|
||||
if (t != nullptr)
|
||||
SendString(fieldname, t);
|
||||
else
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, char const* t)
|
||||
{
|
||||
if (t != nullptr)
|
||||
SendString(fieldname, t);
|
||||
else
|
||||
SendToCSharpNullPtr(fieldname);
|
||||
}
|
||||
|
||||
#if XR_TYPE_SAFE_HANDLES
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrPath t)
|
||||
{
|
||||
SendXrPath(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrPath* t)
|
||||
{
|
||||
SendXrPath(fieldname, *t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrAction t)
|
||||
{
|
||||
SendXrAction(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrAction* t)
|
||||
{
|
||||
SendXrAction(fieldname, *t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrActionSet t)
|
||||
{
|
||||
SendXrActionSet(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrActionSet* t)
|
||||
{
|
||||
SendXrActionSet(fieldname, *t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrSpace t)
|
||||
{
|
||||
SendXrSpace(fieldname, t);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrSpace* t)
|
||||
{
|
||||
SendXrSpace(fieldname, *t);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_DECL(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType*>(const char* fieldname, structType* t, int lenParam);
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_PTR_DECL(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType**>(const char* fieldname, structType** t, int lenParam);
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_CONST_PTR_DECL(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType const* const*>(const char* fieldname, structType const* const* t, int lenParam);
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_DECL)
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_PTR_DECL)
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_CONST_PTR_DECL)
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCT_DECL(structType, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType t);
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCT_PTR_DECL(structType, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType* t);
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCT_CONST_PTR(structType, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType const* t);
|
||||
|
||||
// Fwd declare base structs
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_STRUCT_DECL)
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_STRUCT_PTR_DECL)
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_STRUCT_CONST_PTR)
|
||||
|
||||
// Fwd declare basic structs
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCT_DECL)
|
||||
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCT_PTR_DECL)
|
||||
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCT_CONST_PTR)
|
||||
|
||||
// Fwd declare full structs
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCT_DECL)
|
||||
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCT_PTR_DECL)
|
||||
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCT_CONST_PTR)
|
||||
|
||||
#define SEND_TO_CSHARP_INDIVIDUAL_FIELDS(structname) \
|
||||
SendToCSharp(#structname, t.structname);
|
||||
|
||||
#define SEND_TO_CSHARP_INDIVIDUAL_FIELDS_PTR(structname) \
|
||||
SendToCSharp(#structname, t->structname);
|
||||
|
||||
#define SEND_TO_CSHARP_ARRAYS(structname, structlen) \
|
||||
if (!SendToCSharpBaseStructArray(#structname, t.structname, t.structlen)) \
|
||||
{ \
|
||||
for (uint32_t i = 0; i < t.structlen; ++i) \
|
||||
SendToCSharp(#structname, t.structname[i]); \
|
||||
}
|
||||
|
||||
#define SEND_TO_CSHARP_ARRAYS_PTR(structname, structlen) \
|
||||
if (!SendToCSharpBaseStructArray(#structname, t->structname, t->structlen)) \
|
||||
{ \
|
||||
for (uint32_t i = 0; i < t->structlen; ++i) \
|
||||
SendToCSharp(#structname, t->structname[i]); \
|
||||
}
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCTS(structname, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structname t) \
|
||||
{ \
|
||||
StartStruct(fieldname, #structname); \
|
||||
XR_LIST_STRUCT_##structname(SEND_TO_CSHARP_INDIVIDUAL_FIELDS); \
|
||||
XR_LIST_STRUCT_ARRAYS_##structname(SEND_TO_CSHARP_ARRAYS); \
|
||||
EndStruct(); \
|
||||
}
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCTS_PTRS(structname, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structname* t) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
StartStruct(fieldname, #structname); \
|
||||
XR_LIST_STRUCT_##structname(SEND_TO_CSHARP_INDIVIDUAL_FIELDS_PTR); \
|
||||
XR_LIST_STRUCT_ARRAYS_##structname(SEND_TO_CSHARP_ARRAYS_PTR); \
|
||||
EndStruct(); \
|
||||
}
|
||||
|
||||
#define SEND_TO_CSHARP_STRUCTS_CONST_PTRS(structname, ...) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, const structname* t) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
StartStruct(fieldname, #structname); \
|
||||
XR_LIST_STRUCT_##structname(SEND_TO_CSHARP_INDIVIDUAL_FIELDS_PTR); \
|
||||
XR_LIST_STRUCT_ARRAYS_##structname(SEND_TO_CSHARP_ARRAYS_PTR); \
|
||||
EndStruct(); \
|
||||
}
|
||||
|
||||
// Basic Structs
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCTS)
|
||||
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCTS_PTRS)
|
||||
|
||||
XR_LIST_BASIC_STRUCTS(SEND_TO_CSHARP_STRUCTS_CONST_PTRS)
|
||||
|
||||
// Full Structs
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCTS)
|
||||
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCTS_PTRS)
|
||||
|
||||
XR_LIST_STRUCTURE_TYPES(SEND_TO_CSHARP_STRUCTS_CONST_PTRS)
|
||||
|
||||
#include "serialize_structs_base.h"
|
||||
@@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#define BASE_TO_TYPE(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName* realType = reinterpret_cast<typeName*>(&t); \
|
||||
SendToCSharp(fieldname, realType); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT(structType) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType t) \
|
||||
{ \
|
||||
switch (t.type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, "<Unknown>"); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT)
|
||||
|
||||
#define BASE_TO_TYPE_PTR(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName* realType = reinterpret_cast<typeName*>(t); \
|
||||
SendToCSharp(fieldname, realType); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_PTR(structType) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType* t) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
switch (t->type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE_PTR); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, t->type); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_PTR)
|
||||
|
||||
#define BASE_TO_TYPE_CONST_PTR(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName const* realType = reinterpret_cast<typeName const*>(t); \
|
||||
SendToCSharp(fieldname, realType); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_CONST_PTR(structType) \
|
||||
template <> \
|
||||
void SendToCSharp<>(const char* fieldname, structType const* t) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
switch (t->type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE_CONST_PTR); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, "<Unknown>"); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_CONST_PTR)
|
||||
|
||||
// If we serializing a base struct array such as XrSwapchainImageBaseHeader,
|
||||
// we can only loop over the array of the real type.
|
||||
|
||||
#define BASE_TO_TYPE_ARRAY(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName* realTypeArray = reinterpret_cast<typeName*>(t); \
|
||||
for (int i = 0; i < lenParam; ++i) \
|
||||
SendToCSharp(fieldname, realTypeArray[i]); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_ARRAY(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType*>(const char* fieldname, structType* t, int lenParam) \
|
||||
{ \
|
||||
if (t == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
switch (t[0].type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE_ARRAY); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, "<Unknown>"); \
|
||||
break; \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_ARRAY)
|
||||
|
||||
#define BASE_TO_TYPE_ARRAY_PTR(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName** realTypeArray = reinterpret_cast<typeName**>(t); \
|
||||
SendToCSharp(fieldname, realTypeArray[i]); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_ARRAY_PTR(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType**>(const char* fieldname, structType** t, int lenParam) \
|
||||
{ \
|
||||
if (t == nullptr || t[0] == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
for (int i = 0; i < lenParam; ++i) \
|
||||
{ \
|
||||
switch (t[i]->type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE_ARRAY_PTR); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, "<Unknown>"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_ARRAY_PTR)
|
||||
|
||||
#define BASE_TO_TYPE_ARRAY_CONST_PTR(typeName, typeType) \
|
||||
case typeType: \
|
||||
{ \
|
||||
typeName const* const* realTypeArray = reinterpret_cast<typeName const* const*>(t); \
|
||||
SendToCSharp(fieldname, realTypeArray[i]); \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define SEND_TO_CSHARP_BASE_STRUCT_ARRAY_CONST_PTR(structType) \
|
||||
template <> \
|
||||
bool SendToCSharpBaseStructArray<structType const* const*>(const char* fieldname, structType const* const* t, int lenParam) \
|
||||
{ \
|
||||
if (t == nullptr || t[0] == nullptr) \
|
||||
{ \
|
||||
SendToCSharpNullPtr(fieldname); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
for (int i = 0; i < lenParam; ++i) \
|
||||
{ \
|
||||
switch (t[i]->type) \
|
||||
{ \
|
||||
XR_LIST_BASE_STRUCT_TYPES_##structType(BASE_TO_TYPE_ARRAY_CONST_PTR); \
|
||||
case XR_TYPE_UNKNOWN: \
|
||||
default: \
|
||||
SendToCSharp(fieldname, "<Unknown>"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
XR_LIST_BASE_STRUCTS(SEND_TO_CSHARP_BASE_STRUCT_ARRAY_CONST_PTR)
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrEventDataBuffer* t)
|
||||
{
|
||||
XrEventDataBaseHeader* evt = reinterpret_cast<XrEventDataBaseHeader*>(t);
|
||||
SendToCSharp("varying", evt);
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrDebugUtilsMessengerCreateInfoEXT const* t)
|
||||
{
|
||||
SendToCSharp(fieldname, "<TODO: XrDebugUtilsMessengerCreateInfoEXT>");
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrSpatialGraphNodeSpaceCreateInfoMSFT const* t)
|
||||
{
|
||||
SendToCSharp(fieldname, "<TODO: XrSpatialGraphNodeSpaceCreateInfoMSFT>");
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrInteractionProfileAnalogThresholdVALVE* t)
|
||||
{
|
||||
SendToCSharp(fieldname, "<TODO: XrInteractionProfileAnalogThresholdVALVE>");
|
||||
}
|
||||
|
||||
template <>
|
||||
void SendToCSharp<>(const char* fieldname, XrWorldMeshBufferML* t)
|
||||
{
|
||||
SendToCSharp(fieldname, "<TODO: XrWorldMeshBufferML>");
|
||||
}
|
||||
Reference in New Issue
Block a user