Skip to content

Conversation

@Yarwin
Copy link
Contributor

@Yarwin Yarwin commented Dec 17, 2025

@Yarwin Yarwin added bug c: engine Godot classes (nodes, resources, ...) labels Dec 17, 2025
@Yarwin Yarwin force-pushed the bugfix/set-proper-init-level-for-openxrextensionwrapper branch from 8893617 to 1f72724 Compare December 17, 2025 09:01
@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1445

@Bromeon Bromeon changed the title Set proper initialization level for OpenXrExtensionWrapper. Set proper initialization level for OpenXrExtensionWrapper Dec 17, 2025
@RubberDuckShobe
Copy link

This unfortunately didn't seem to fix my issue.

Console output of exported game, trying to register the extension wrapper at InitLevel::Core:

~/Documents/Godot Projects/mirrorball/exports
❯ XR_ENABLE_API_LAYERS=XR_APILAYER_LUNARG_api_dump XR_API_DUMP_EXPORT_TYPE=html XR_API_DUMP_FILE_NAME=api_dump.html ./mirrorball.x86_64
Initialize godot-rust (API v4.5.stable.official, runtime v4.5.1.stable.official, safeguards strict)
setting min level
wow init!!
ERROR: Failed to retrieve non-existent singleton 'ClassDB'.
   at: get_singleton_object (core/config/engine.cpp:308)
ERROR: [panic /home/m1nt_/.cargo/git/checkouts/gdext-0d37dbac4138f9c2/1f72724/godot-core/src/obj/gd.rs:614]
  Gd::from_obj_sys() called with null pointer
  Context: failed to initialize GDExtension level `Core`
   at: godot_core::private::set_gdext_hook::{{closure}} (/home/m1nt_/.cargo/git/checkouts/gdext-0d37dbac4138f9c2/1f72724/godot-core/src/private.rs:343)
(backtrace disabled, run application with `RUST_BACKTRACE=1` environment variable)
Godot Engine v4.5.1.stable.official.f62fdbde1 - https://godotengine.org

Same error can also be observed when trying to register it at InitLevel::Servers, tested when hitting "Play" in the editor this time:
image

My code (previously posted in the Discord as well)

use std::ffi::c_void;

use godot::{
    classes::{IOpenXrExtensionWrapper, OpenXrExtensionWrapper},
    meta::RawPtr,
    prelude::*,
};
use openxr_sys::{OverlaySessionCreateFlagsEXTX, SessionCreateInfoOverlayEXTX};

struct MyExtension;

#[gdextension]
unsafe impl ExtensionLibrary for MyExtension {
    fn min_level() -> InitLevel {
        godot_print!("setting min level");
        InitLevel::Core
    }

    fn on_level_init(level: InitLevel) {
        // issue also appears when this is InitLevel::Servers !
        if level == InitLevel::Core {
            godot_print!("wow init!!");
            let mut overlay_ext = XrExtxOverlayExtension::new_alloc();
            overlay_ext.register_extension_wrapper();
        }
    }
}

#[derive(GodotClass)]
#[class(tool, init, base=OpenXrExtensionWrapper)]
struct XrExtxOverlayExtension {
    base: Base<OpenXrExtensionWrapper>,
}

#[godot_api]
impl IOpenXrExtensionWrapper for XrExtxOverlayExtension {
    fn on_instance_created(&mut self, instance: u64) {
        godot_print!("instance created");
    }

    fn get_requested_extensions(&mut self) -> VarDictionary {
        godot_print!("getting requested extensions");

        // godot requests extensions as a dictionary where the key is a string
        // the value determining if the extension should be enabled is a bool*
        // if it's a nullptr, it means the extension is *mandatory*
        unsafe {
            vdict! {
               "XR_EXTX_overlay": RawPtr::<*const bool>::new(std::ptr::null())
            }
        }
    }

    unsafe fn set_session_create_and_get_next_pointer_rawptr(
        &mut self,
        p_next_pointer: RawPtr<*mut c_void>,
    ) -> u64 {
        godot_print!("next ptr {:?}", p_next_pointer);
        // there's probably a better way to do this than with a Box
        // but the entire function doesn't run yet anyway so not really a big deal?
        let overlay = Box::new(SessionCreateInfoOverlayEXTX {
            ty: SessionCreateInfoOverlayEXTX::TYPE,
            next: p_next_pointer.ptr(),
            create_flags: OverlaySessionCreateFlagsEXTX::EMPTY,
            session_layers_placement: 5,
        });
        let final_ptr = Box::into_raw(overlay);
        godot_print!("final ptr: {:?}", final_ptr);
        final_ptr as u64
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug c: engine Godot classes (nodes, resources, ...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants