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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 25 additions & 42 deletions src/core/oxr_utils/cpp/inc/oxr_utils/oxr_funcs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,65 +52,48 @@ struct OpenXRCoreFunctions
PFN_xrGetActionStateFloat xrGetActionStateFloat;
PFN_xrGetActionStateVector2f xrGetActionStateVector2f;

OpenXRCoreFunctions()
: xrGetSystem(nullptr),
xrGetSystemProperties(nullptr),
xrCreateReferenceSpace(nullptr),
xrDestroySpace(nullptr),
xrLocateSpace(nullptr),
xrStringToPath(nullptr),
xrCreateActionSet(nullptr),
xrDestroyActionSet(nullptr),
xrCreateAction(nullptr),
xrSuggestInteractionProfileBindings(nullptr),
xrAttachSessionActionSets(nullptr),
xrCreateActionSpace(nullptr),
xrSyncActions(nullptr),
xrGetActionStateBoolean(nullptr),
xrGetActionStateFloat(nullptr),
xrGetActionStateVector2f(nullptr)
{
}

// Load all core functions from an instance using the provided xrGetInstanceProcAddr
bool load(XrInstance instance, PFN_xrGetInstanceProcAddr getProcAddr)
static OpenXRCoreFunctions load(XrInstance instance, PFN_xrGetInstanceProcAddr getProcAddr)
{
if (!getProcAddr)
{
return false;
}
assert(getProcAddr);
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert will only trigger in debug builds. Consider using an explicit runtime check with a clear error message (e.g., if (!getProcAddr) throw std::invalid_argument("getProcAddr cannot be null");) to ensure consistent behavior across build configurations.

Suggested change
assert(getProcAddr);
if (!getProcAddr)
{
throw std::invalid_argument("getProcAddr cannot be null");
}

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not supposed to happen in production, and is not to be handled by the caller.


OpenXRCoreFunctions results{};
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct members are not default-initialized in the new design. Without an explicit constructor or member initializers, the function pointers will have indeterminate values. Add = nullptr initializers to each member declaration or define a default constructor that initializes all members to nullptr.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{} will initialize all members to zero

bool success = true;

success &=
XR_SUCCEEDED(getProcAddr(instance, "xrGetSystem", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetSystem)));
XR_SUCCEEDED(getProcAddr(instance, "xrGetSystem", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrGetSystem)));
success &= XR_SUCCEEDED(getProcAddr(
instance, "xrGetSystemProperties", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetSystemProperties)));
instance, "xrGetSystemProperties", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrGetSystemProperties)));
success &= XR_SUCCEEDED(getProcAddr(
instance, "xrCreateReferenceSpace", reinterpret_cast<PFN_xrVoidFunction*>(&xrCreateReferenceSpace)));
instance, "xrCreateReferenceSpace", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrCreateReferenceSpace)));
success &=
XR_SUCCEEDED(getProcAddr(instance, "xrDestroySpace", reinterpret_cast<PFN_xrVoidFunction*>(&xrDestroySpace)));
XR_SUCCEEDED(getProcAddr(instance, "xrDestroySpace", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrDestroySpace)));
success &=
XR_SUCCEEDED(getProcAddr(instance, "xrLocateSpace", reinterpret_cast<PFN_xrVoidFunction*>(&xrLocateSpace)));
XR_SUCCEEDED(getProcAddr(instance, "xrLocateSpace", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrLocateSpace)));

if (!success)
{
throw std::runtime_error("Failed to load core OpenXR functions");
}

// Action system functions (optional, for controller tracking)
// Note: These don't fail the load if not available, as they're only needed by controller tracker
getProcAddr(instance, "xrStringToPath", reinterpret_cast<PFN_xrVoidFunction*>(&xrStringToPath));
getProcAddr(instance, "xrCreateActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&xrCreateActionSet));
getProcAddr(instance, "xrDestroyActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&xrDestroyActionSet));
getProcAddr(instance, "xrCreateAction", reinterpret_cast<PFN_xrVoidFunction*>(&xrCreateAction));
getProcAddr(instance, "xrStringToPath", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrStringToPath));
getProcAddr(instance, "xrCreateActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrCreateActionSet));
getProcAddr(instance, "xrDestroyActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrDestroyActionSet));
getProcAddr(instance, "xrCreateAction", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrCreateAction));
getProcAddr(instance, "xrSuggestInteractionProfileBindings",
reinterpret_cast<PFN_xrVoidFunction*>(&xrSuggestInteractionProfileBindings));
reinterpret_cast<PFN_xrVoidFunction*>(&results.xrSuggestInteractionProfileBindings));
getProcAddr(
instance, "xrAttachSessionActionSets", reinterpret_cast<PFN_xrVoidFunction*>(&xrAttachSessionActionSets));
getProcAddr(instance, "xrCreateActionSpace", reinterpret_cast<PFN_xrVoidFunction*>(&xrCreateActionSpace));
getProcAddr(instance, "xrSyncActions", reinterpret_cast<PFN_xrVoidFunction*>(&xrSyncActions));
getProcAddr(instance, "xrGetActionStateBoolean", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetActionStateBoolean));
getProcAddr(instance, "xrGetActionStateFloat", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetActionStateFloat));
instance, "xrAttachSessionActionSets", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrAttachSessionActionSets));
getProcAddr(instance, "xrCreateActionSpace", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrCreateActionSpace));
getProcAddr(instance, "xrSyncActions", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrSyncActions));
getProcAddr(instance, "xrGetActionStateBoolean", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrGetActionStateBoolean));
getProcAddr(instance, "xrGetActionStateFloat", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrGetActionStateFloat));
getProcAddr(
instance, "xrGetActionStateVector2f", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetActionStateVector2f));
instance, "xrGetActionStateVector2f", reinterpret_cast<PFN_xrVoidFunction*>(&results.xrGetActionStateVector2f));

return success;
return results;
}
};

Expand Down
9 changes: 2 additions & 7 deletions src/core/xrio/cpp/controllertracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ bool get_vector2_action_state(XrSession session,

// Constructor - throws std::runtime_error on failure
ControllerTracker::Impl::Impl(const OpenXRSessionHandles& handles)
: session_(handles.session),
: core_funcs_(OpenXRCoreFunctions::load(handles.instance, handles.xrGetInstanceProcAddr)),
session_(handles.session),
base_space_(handles.space),
grip_pose_action_(XR_NULL_HANDLE),
aim_pose_action_(XR_NULL_HANDLE),
Expand All @@ -90,12 +91,6 @@ ControllerTracker::Impl::Impl(const OpenXRSessionHandles& handles)
left_hand_path_(XR_NULL_PATH),
right_hand_path_(XR_NULL_PATH)
{
// Load core OpenXR functions dynamically using the provided xrGetInstanceProcAddr
if (!core_funcs_.load(handles.instance, handles.xrGetInstanceProcAddr))
{
throw std::runtime_error("Failed to load core OpenXR functions for ControllerTracker");
}

// Create action set for both controllers
XrActionSetCreateInfo action_set_info{ XR_TYPE_ACTION_SET_CREATE_INFO };
strcpy(action_set_info.actionSetName, "controller_tracking");
Expand Down
6 changes: 1 addition & 5 deletions src/core/xrio/cpp/handtracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ HandTracker::Impl::Impl(const OpenXRSessionHandles& handles)
pfn_locate_hand_joints_(nullptr)
{
// Load core OpenXR functions dynamically using the provided xrGetInstanceProcAddr
OpenXRCoreFunctions core_funcs;
if (!core_funcs.load(handles.instance, handles.xrGetInstanceProcAddr))
{
throw std::runtime_error("Failed to load core OpenXR functions for HandTracker");
}
auto core_funcs = OpenXRCoreFunctions::load(handles.instance, handles.xrGetInstanceProcAddr);

// Check if system supports hand tracking
XrSystemId system_id;
Expand Down
10 changes: 3 additions & 7 deletions src/core/xrio/cpp/headtracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ namespace core
// ============================================================================

// Constructor - throws std::runtime_error on failure
HeadTracker::Impl::Impl(const OpenXRSessionHandles& handles) : base_space_(handles.space)
HeadTracker::Impl::Impl(const OpenXRSessionHandles& handles)
: core_funcs_(OpenXRCoreFunctions::load(handles.instance, handles.xrGetInstanceProcAddr)),
base_space_(handles.space)
{
// Load core OpenXR functions dynamically using the provided xrGetInstanceProcAddr
if (!core_funcs_.load(handles.instance, handles.xrGetInstanceProcAddr))
{
throw std::runtime_error("Failed to load core OpenXR functions for HeadTracker");
}

// Create VIEW space for head tracking (represents HMD pose)
XrReferenceSpaceCreateInfo create_info{ XR_TYPE_REFERENCE_SPACE_CREATE_INFO };
create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
Expand Down
5 changes: 2 additions & 3 deletions src/core/xrio/cpp/inc/xrio/controllertracker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class ControllerTracker : public ITracker
const ControllerSnapshot& get_snapshot(Hand hand) const;

private:
const OpenXRCoreFunctions core_funcs_;

XrSession session_;
XrSpace base_space_;

Expand Down Expand Up @@ -122,9 +124,6 @@ class ControllerTracker : public ITracker
// Controller data for both hands
ControllerSnapshot left_snapshot_;
ControllerSnapshot right_snapshot_;

// Core functions
OpenXRCoreFunctions core_funcs_;
};

// Weak pointer to impl (owned by session)
Expand Down
2 changes: 1 addition & 1 deletion src/core/xrio/cpp/inc/xrio/headtracker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ class HeadTracker : public ITracker
const HeadPose& get_head() const;

private:
const OpenXRCoreFunctions core_funcs_;
XrSpace base_space_;
XrSpacePtr view_space_;
HeadPose head_;
OpenXRCoreFunctions core_funcs_;
};

// Weak pointer to impl (owned by session)
Expand Down