stechyo / godot-steam-audio

Immersive spatial audio extension for Godot, using Valve's SteamAudio
MIT License
349 stars 9 forks source link

macos editor support #53

Open fabius opened 7 months ago

fabius commented 7 months ago

As of right now, this addon cannot be used on macos.

Compiling this using

scons target=template_debug debug_symbols=true

does not spit out the required libgodot-steam-audio.macos.template_debug.framework file either. Though I don't event know if it's supposed to or if it has to be generated with xcodebuild beforehand.

stechyo commented 7 months ago

Might be a problem with the scons file, but admittedly I don't have a Mac to test this with. What happens if you replace these lines with:

if env["platform"] == "macos":
    library = env.SharedLibrary(
        "project/addons/godot-steam-audio/bin/godot-steam-audio{0}{1}.framework/godot-steam-audio.{0}.{1}".format(env["suffix"], env["SHLIBSUFFIX"]),
        source=sources,
    )
else:
    library = env.SharedLibrary(
        "project/addons/godot-steam-audio/bin/godot-steam-audio{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
        source=sources,
    )

?

EugeneVanchugov commented 6 months ago

This is how I made it to build the macos binary with required path:

valid_path = "project/addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib"

suffix = env["suffix"]
lib_suffix = env["SHLIBSUFFIX"]
# suffix:  .macos.template_debug.universal
print("suffix: ", suffix)
# lib_suffix:  .dylib
print("lib_suffix: ", lib_suffix)

# Link flags and libraries based on the building platform
if env["platform"] == "linux":
    # NOTHING HAS BEEN CHANGED HERE
elif env["platform"] == "macos":
    macos_lib_path = "project/addons/godot-steam-audio/bin/libgodot-steam-audio%s.framework/libgodot-steam-audio%s%s" % (suffix, suffix, lib_suffix)

    # Assert we constructed the path correctly
    if (not macos_lib_path == valid_path):
        print("Required path: ", valid_path)
        print("Actual path: ", macos_lib_path)
        raise Exception("The path to the library is not correct. Please check the path in SConstruct")

    library = env.SharedLibrary(
        macos_lib_path,
        source=sources,
    )
else:
    library = env.SharedLibrary(
        "project/addons/godot-steam-audio/bin/godot-steam-audio%s%s" % (suffix, lib_suffix),
        source=sources,
    )

Default(library)

And changed this line in src/godot-steam-audio/project/addons/godot-steam-audio/bin/libgodot-steam-audio.gdextension:

macos.debug = "res://addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib"

This is the error message after previous actions:

ERROR: Can't open dynamic library: /Users/eugene/Programming/Godot/src/godot-steam-audio/project/addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib. Error: dlopen(/Users/eugene/Programming/Godot/src/godot-steam-audio/project/addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib, 0x0002): symbol not found in flat namespace '_iplAmbisonicsDecodeEffectApply'.
   at: open_dynamic_library (platform/macos/os_macos.mm:234)
ERROR: GDExtension dynamic library not found: /Users/eugene/Programming/Godot/src/godot-steam-audio/project/addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib
   at: open_library (core/extension/gdextension.cpp:719)
ERROR: Failed loading resource: res://addons/godot-steam-audio/bin/libgodot-steam-audio.gdextension. Make sure resources have been imported by opening the project in the editor at least once.
   at: _load (core/io/resource_loader.cpp:275)
ERROR: Error loading extension: res://addons/godot-steam-audio/bin/libgodot-steam-audio.gdextension
   at: load_extensions (core/extension/gdextension_manager.cpp:234)

The original Steam Audio macos binary's size is around 26 MB. But the godot-steam-audio binary has a size of only 763 Kb.

Seems like something is compiling wrong to me, but I have a no experience with Godot or Steam Audio sources.

If you have any clues on what might be wrong here, I'll be happy to test your ideas on my mac. After everything will be compiled successfully, I would provide you a macos Godot executable.

Thanks!

stechyo commented 6 months ago

The steam audio and godot-steam-audio binaries are different and both must be provided (in Win/Linux, they’re both in the same folder). You may just need to place the SteamAudio binary in the same folder.

EugeneVanchugov commented 6 months ago

The steam audio and godot-steam-audio binaries are different and both must be provided (in Win/Linux, they’re both in the same folder). You may just need to place the SteamAudio binary in the same folder.

I tried placing Steam Audio binaries next to the godot-steam-audio binaries inside framework and outside, next to the framework directory. It didn't help.

This is how it looks:

image

The log output hasn't changed.

EugeneVanchugov commented 6 months ago

I managed to run Godot with SteamAudio components!

These are the steps I did:

  1. Modify SConstruct by adding macos section:

    elif env["platform"] == "macos":
    env.Append(LIBPATH=["src/lib/steamaudio/lib/macos-x64"])
    env.Append(LIBS=["libphonon.dylib"])
    macos_lib_path = "project/addons/godot-steam-audio/bin/libgodot-steam-audio%s.framework/libgodot-steam-audio%s%s" % (suffix, suffix, lib_suffix)
    library = env.SharedLibrary(
        macos_lib_path,
        source=sources,
    )
  2. Put Steam Audio binaries (libphonon.dylib) into src/lib/steamaudio/lib/macos-x64 directory.

  3. Run scons target=template_debug

  4. Modify project/addons/godot-steam-audio/bin/libgodot-steam-audio.gdextension:

    macos.debug = "res://addons/godot-steam-audio/bin/libgodot-steam-audio.macos.template_debug.universal.framework/libgodot-steam-audio.macos.template_debug.universal.dylib"
  5. Build Godot from source and put Steam Audio libphonon.dylib binary right next to the built Godot executable.

  6. Run Godot.

After that the previous errors are gone and editor works.

But now I get an error when trying to run demo project:

Godot Engine v4.2.2.stable.custom_build.231d764ea - https://godotengine.org
Vulkan API 1.2.280 - Forward+ - Using Vulkan Device #0: Apple - Apple M2 Pro

2024-05-10 21:27:21.453 Godot[7693:60172] WARNING: AVCaptureDeviceTypeExternal is deprecated for Continuity Cameras. Please use AVCaptureDeviceTypeContinuityCamera and add NSCameraUseContinuityCameraDeviceType to your Info.plist.
WARNING: Blend file import is enabled in the project settings, but no Blender path is configured in the editor settings. Blend files will not be imported.
     at: _editor_init (modules/gltf/register_types.cpp:63)
Godot Engine v4.2.2.stable.custom_build.231d764ea - https://godotengine.org
Vulkan API 1.2.280 - Forward+ - Using Vulkan Device #0: Apple - Apple M2 Pro

2024-05-10 21:27:41.827 Godot[7755:60663] WARNING: AVCaptureDeviceTypeExternal is deprecated for Continuity Cameras. Please use AVCaptureDeviceTypeContinuityCamera and add NSCameraUseContinuityCameraDeviceType to your Info.plist.
[godot-steam-audio] Initializing SteamAudioServer global state
ERROR: [godot-steam-audio] Unspecified error in init
   at: push_error (core/variant/variant_utility.cpp:1091)
ERROR: [godot-steam-audio] Failed to handle external dependency in init
   at: push_error (core/variant/variant_utility.cpp:1091)
ERROR: [godot-steam-audio] Failed to handle external dependency in init
   at: push_error (core/variant/variant_utility.cpp:1091)
[godot-steam-audio] Initialized SteamAudioServer global state
WARNING: A Thread object is being destroyed without its completion having been realized.
Please call wait_to_finish() on it to ensure correct cleanup.
     at: ~Thread (core/os/thread.cpp:104)

================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.2.2.stable.custom_build (231d764ea1eb895359c7ce7cac391d5613618f7e)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] 1   libsystem_platform.dylib            0x00000001837cf584 _sigtramp + 56
[2] 2   libgodot-steam-audio.macos.template 0x000000010e338c48 libgodot-steam-audio.macos.template + 35912
[3] Object::notification(int, bool) (in Godot) + 112
[4] Node::_propagate_enter_tree() (in Godot) + 224
[5] Node::_propagate_enter_tree() (in Godot) + 572
[6] Node::_propagate_enter_tree() (in Godot) + 572
[7] Node::_propagate_enter_tree() (in Godot) + 572
[8] Node::_propagate_enter_tree() (in Godot) + 572
[9] Node::_propagate_enter_tree() (in Godot) + 572
[10] Node::_set_tree(SceneTree*) (in Godot) + 60
[11] OS_MacOS::run() (in Godot) + 52
[12] main (in Godot) + 304
[13] 13  dyld                                0x00000001834160e0 start + 2360
-- END OF BACKTRACE --
================================================================
stechyo commented 6 months ago

Hm... the SteamAudio binary should stay in the same folder as libgodot-steam-audio. I was gonna suggest what you did, appending LIBS, so that's good. Try moving the binary around, if it doesn't work try scons target=template_debug debug_symbols=yes and see if it shows a nicer backtrace on crash.

EugeneVanchugov commented 6 months ago

Tried building godot-steam-audio with these flags, but no other info in Godot logs was shown. But I found some clues in Apple crash reporter:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib                 0x183766a60 __pthread_kill + 8
1   libsystem_pthread.dylib                0x18379ec20 pthread_kill + 288
2   libsystem_c.dylib                      0x1836aba20 abort + 180
3   Godot                                  0x1030249dc 0x102c90000 + 3754460
4   libsystem_platform.dylib               0x1837cf584 _sigtramp + 56
5   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10cd0c814 SteamAudioGeometry::register_geometry() + 28 (geometry.cpp:95) [inlined]
6   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10cd0c814 SteamAudioGeometry::ready_internal() + 36 (geometry.cpp:38) [inlined]
7   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10cd0c814 SteamAudioGeometry::_notification(int) + 92 (geometry.cpp:44)
8   Godot                                  0x106469d2c Object::notification(int, bool) + 112
9   Godot                                  0x1048d35dc Node::_propagate_enter_tree() + 224
10  Godot                                  0x1048d3738 Node::_propagate_enter_tree() + 572
11  Godot                                  0x1048d3738 Node::_propagate_enter_tree() + 572
12  Godot                                  0x1048d3738 Node::_propagate_enter_tree() + 572
13  Godot                                  0x1048d3738 Node::_propagate_enter_tree() + 572
14  Godot                                  0x1048d3738 Node::_propagate_enter_tree() + 572
15  Godot                                  0x1048d92b4 Node::_set_tree(SceneTree*) + 60
16  Godot                                  0x10302116c OS_MacOS::run() + 52
17  Godot                                  0x10304f61c main + 304
18  dyld                                   0x1834160e0 start + 2360

Also I tried moving around binaries in case if Steam Audio lib keeps some state inside, but it did nothing.

UPD: Just tried launching dynamic_test.tscn. Received slightly different error message:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib                 0x183766a60 __pthread_kill + 8
1   libsystem_pthread.dylib                0x18379ec20 pthread_kill + 288
2   libsystem_c.dylib                      0x1836aba20 abort + 180
3   Godot                                  0x1011349dc 0x100da0000 + 3754460
4   libsystem_platform.dylib               0x1837cf584 _sigtramp + 56
5   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10ae23fac SteamAudioDynamicGeometry::create_geometry() + 464 (geometry_dynamic.cpp:117)
6   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10ae2410c SteamAudioDynamicGeometry::ready_internal() + 20 (geometry_dynamic.cpp:55) [inlined]
7   libgodot-steam-audio.macos.template_debug.universal.dylib          0x10ae2410c SteamAudioDynamicGeometry::_notification(int) + 100 (geometry_dynamic.cpp:40)

SteamAudioGeometry::register_geometry() calls SteamAudioServer::add_static_mesh SteamAudioDynamicGeometry::create_geometry() uses iplStaticMeshAdd

image

Seems that function iplStaticMeshAdd is the root cause.

/** Adds a static mesh to a scene.

    This function should be called after \c iplStaticMeshCreate, or at any point after \c iplStaticMeshRemove,
    for the static mesh to start affecting sound propagation.

    After calling this function, \c iplSceneCommit must be called for the changes to take effect.

    \param  staticMesh  The static mesh to add.
    \param  scene       The scene to which to add the static mesh. This must be the scene which was passed when
                        calling \c iplStaticMeshCreate.
*/
IPLAPI void IPLCALL iplStaticMeshAdd(IPLStaticMesh staticMesh, IPLScene scene);
EugeneVanchugov commented 6 months ago

I think there is a dynamic lib linkage problem or something like that. I don't have a skill to debug this and get any further on my own.

stechyo commented 6 months ago

Understandable :/ it seems to be outside of this extension's scope. I'll check your PR anyway

jdbool commented 1 month ago

@EugeneVanchugov I was also getting these errors:

ERROR: [godot-steam-audio] Unspecified error in init
   at: push_error (core/variant/variant_utility.cpp:1091)
ERROR: [godot-steam-audio] Failed to handle external dependency in init
   at: push_error (core/variant/variant_utility.cpp:1091)
ERROR: [godot-steam-audio] Failed to handle external dependency in init
   at: push_error (core/variant/variant_utility.cpp:1091)

Then I changed the Scene Type in my SteamAudioConfig from Embree to Default -- works great at runtime for me now on macOS! Maybe Embree doesn't work on ARM?

jdbool commented 1 month ago

If it helps, one other hack I had to do to get it running on mac was placing libphonon.dylib in /Applications/Godot.app/Contents/Frameworks

stechyo commented 1 month ago

Opened https://github.com/ValveSoftware/steam-audio/issues/380. Embree might not be enabled on Apple Silicon.