Skip to content

iOS Support #87

Closed
Closed

Description

@cart

It should be possible to run Bevy Apps on iOS

Activity

  1. added
    A-Build-SystemRelated to build systems or continuous integration
    C-FeatureA new feature, making something new possible
    on Aug 12, 2020
  2. MichaelHills commented on Aug 21, 2020

    @MichaelHills
    Contributor

    Hi, what’s involved in setting up Bevy on iOS? My understanding is that it uses winit which should already support iOS?

  3. MichaelHills commented on Aug 22, 2020

    @MichaelHills
    Contributor

    I followed this guide to just get a Rust lib working from an ios project. Then I tried to substitute a bevy example app in. During cargo lipo --release it fails to build bevy-glsl-to-spirv.

    It looks like there's no prebuilt binary in that repo so it tries to build glslang and then cmake fails

      -- Check for working C compiler: /usr/bin/cc -- broken
    ...
    Building C object CMakeFiles/cmTC_97014.dir/testCCompiler.c.o
          /usr/bin/cc   -fPIC -m64 -m64 -mios-simulator-version-min=7.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk -fembed-bitcode  -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk   -o CMakeFiles/cmTC_97014.dir/testCCompiler.c.o   -c /Users/mikeh/rust-ios-example/rust/target/x86_64-apple-ios/release/build/bevy-glsl-to-spirv-51cc402e67486116/out/build/CMakeFiles/CMakeTmp/testCCompiler.c
          clang: warning: using sysroot for 'MacOSX' but targeting 'iPhone' [-Wincompatible-sysroot]
    

    Apparently that last line is a key sign something is off. I take it the build for glslang doesn't work properly to target aarch64-apple-ios or x86_64-apple-ios.

  4. MichaelHills commented on Aug 22, 2020

    @MichaelHills
    Contributor

    I tried a couple of things, but I'm new to rust and new to cross-compiling to iOS, though slowly figuring things out. The approach of spawning the glslValidator process probably isn't going to fly on iOS. MoltenVK apparently can build the iOS static lib libglslang.a so I considered trying to interface with that. The bevy-glsl-to-spirv repo says TODO to switch to shaderc-rs so I figured I'd have a crack at that but had trouble cross-compiling for iOS.

    I ended up stubbing out the code in crates/bevy_render/src/shader/shader.rs just to see how far I could get. I also had to disable the optional bevy audio as it didn't compile either (forgot why).

    I managed to finally get something to build, on the simulator gfx-rs / gfx-backend-metal failed with Target OS is incompatible: library was not compiled for the simulator so I ran it on my phone instead to which I got

    EventLoop cannot be run after a call to UIApplicationMain on iOS.
    

    Stopping for tonight. Here's my diff so far to get where i got to...

    diff --git a/Cargo.toml b/Cargo.toml
    index 90b2368d..3254fd6c 100644
    --- a/Cargo.toml
    +++ b/Cargo.toml
    @@ -13,7 +13,8 @@ readme = "README.md"
     exclude = ["assets/**/*", "tools/**/*", ".github/**/*", "crates/**/*"]
     
     [features]
    -default = ["bevy_audio", "bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr", "mp3"]
    +#default = ["bevy_audio", "bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr", "mp3"]
    +default = ["bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr"]
     profiler = ["bevy_ecs/profiler", "bevy_diagnostic/profiler"]
     wgpu_trace = ["bevy_wgpu/trace"]
     
    @@ -22,10 +23,10 @@ png = ["bevy_render/png"]
     hdr = ["bevy_render/hdr"]
     
     # Audio format support (MP3 is enabled by default)
    -mp3 = ["bevy_audio/mp3"]
    -flac = ["bevy_audio/flac"]
    -wav = ["bevy_audio/wav"]
    -vorbis = ["bevy_audio/vorbis"]
    +#mp3 = ["bevy_audio/mp3"]
    +#flac = ["bevy_audio/flac"]
    +#wav = ["bevy_audio/wav"]
    +#vorbis = ["bevy_audio/vorbis"]
     
     serialize = ["bevy_input/serialize"]
     
    @@ -56,7 +57,7 @@ bevy_ui = { path = "crates/bevy_ui", version = "0.1" }
     bevy_window = { path = "crates/bevy_window", version = "0.1" }
     
     # bevy (optional)
    -bevy_audio = { path = "crates/bevy_audio", optional = true, version = "0.1" }
    +#bevy_audio = { path = "crates/bevy_audio", optional = true, version = "0.1" }
     bevy_gltf = { path = "crates/bevy_gltf", optional = true, version = "0.1" }
     bevy_wgpu = { path = "crates/bevy_wgpu", optional = true, version = "0.1" }
     bevy_winit = { path = "crates/bevy_winit", optional = true, version = "0.1" }
    diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml
    index ea29b856..53fe2af4 100644
    --- a/crates/bevy_render/Cargo.toml
    +++ b/crates/bevy_render/Cargo.toml
    @@ -24,7 +24,7 @@ bevy_window = { path = "../bevy_window", version = "0.1" }
     
     # rendering
     spirv-reflect = "0.2.3"
    -bevy-glsl-to-spirv = "0.1.7"
    +#bevy-glsl-to-spirv = { path = "/Users/mikeh/repos/glsl-to-spirv" } #"0.1.7"
     image = { version = "0.23", default-features = false }
     
     # misc
    diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs
    index f963c0c9..dd448e74 100644
    --- a/crates/bevy_render/src/shader/shader.rs
    +++ b/crates/bevy_render/src/shader/shader.rs
    @@ -1,6 +1,6 @@
     use super::ShaderLayout;
     use bevy_asset::Handle;
    -use bevy_glsl_to_spirv::compile;
    +//use bevy_glsl_to_spirv::compile;
     use std::{io::Read, marker::Copy};
     
     /// The stage of a shader
    @@ -11,25 +11,26 @@ pub enum ShaderStage {
         Compute,
     }
     
    -impl Into<bevy_glsl_to_spirv::ShaderType> for ShaderStage {
    -    fn into(self) -> bevy_glsl_to_spirv::ShaderType {
    -        match self {
    -            ShaderStage::Vertex => bevy_glsl_to_spirv::ShaderType::Vertex,
    -            ShaderStage::Fragment => bevy_glsl_to_spirv::ShaderType::Fragment,
    -            ShaderStage::Compute => bevy_glsl_to_spirv::ShaderType::Compute,
    -        }
    -    }
    -}
    +//impl Into<bevy_glsl_to_spirv::ShaderType> for ShaderStage {
    +//    fn into(self) -> bevy_glsl_to_spirv::ShaderType {
    +//        match self {
    +//            ShaderStage::Vertex => bevy_glsl_to_spirv::ShaderType::Vertex,
    +//            ShaderStage::Fragment => bevy_glsl_to_spirv::ShaderType::Fragment,
    +//            ShaderStage::Compute => bevy_glsl_to_spirv::ShaderType::Compute,
    +//        }
    +//    }
    +//}
     
     fn glsl_to_spirv(
         glsl_source: &str,
         stage: ShaderStage,
         shader_defs: Option<&[String]>,
     ) -> Vec<u32> {
    -    let mut output = compile(glsl_source, stage.into(), shader_defs).unwrap();
    +    //let mut output = compile(glsl_source, stage.into(), shader_defs).unwrap();
         let mut spv_bytes = Vec::new();
    -    output.read_to_end(&mut spv_bytes).unwrap();
    -    bytes_to_words(&spv_bytes)
    +    //output.read_to_end(&mut spv_bytes).unwrap();
    +    //bytes_to_words(&spv_bytes)
    +    spv_bytes
     }
     
     fn bytes_to_words(bytes: &[u8]) -> Vec<u32> {
    
  5. MichaelHills commented on Aug 23, 2020

    @MichaelHills
    Contributor

    Looks like cross-compiling iOS stuff with cmake-rs is currently broken rust-lang/cmake-rs#96 so that's probably the source of some of my woes

  6. MichaelHills commented on Aug 23, 2020

    @MichaelHills
    Contributor

    Success! I managed to get the 3d_scene demo loading in portrait mode (albeit a bit warped) on my phone.

    • I pinned cmake-rs to 0.1.43 because that's the version which had the working iOS support
    • Dropped bevy-glsl-to-spirv in favour of using shaderc-rs directly from crates/bevy_render/src/shader/shader.rs
    • Created a main.swift to call out to my bevy_main() function directly which was the 3d_sprite main function renamed like this
    #[no_mangle]
    pub extern fn bevy_main() {
    

    In xcode I had to add the static lib / header and search paths as per this site and I also had to link against lc++. Basically atm I build my "game" as a static lib and then call out to it manually from in an ios xcode project.

    Trying to figure out how to get it into landscape mode now.

  7. cart commented on Aug 23, 2020

    @cart
    MemberAuthor

    Whoa that's huge! Thanks for the hard work here. People are going to love this!

  8. MichaelHills commented on Aug 23, 2020

    @MichaelHills
    Contributor

    No worries. :) When I saw the post on Bevy on HN I thought it looked pretty awesome. I previously had started making a PC game in UE4 but life got busy. Decided I wanted to prototype it out as a mobile game instead and learn some Rust/ECS while I'm at it.

    How should I go about getting stuff landed? I think the switch to shaderc-rs in general can be done now (tested a couple of examples still work). Did you want that to be done inside of bevy-glsl-to-spirv? I've currently just implemented it directly in crates/bevy_render/src/shader/shader.rs while hacking this all up.

    In order to get iOS integration to "just work" the following issues need to be solved properly:

    • Land using shaderc-rs in bevy
    • Get that iOS support commit in cmake-rs fixed up and re-landed there
    • In shaderc-rs I had to edit CMakeLists.txt in the glsl and shaderc submodules (see below), so maybe... get those landed there?
    • Figure out why coreaudio-sys v0.2.5 panics during compile (that was why I had to disable audio)

    shaderc

    diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
    index acf6fb0..4ec0067 100644
    --- a/glslc/CMakeLists.txt
    +++ b/glslc/CMakeLists.txt
    @@ -40,6 +40,7 @@ shaderc_add_asciidoc(glslc_doc_README README)
    
     if(SHADERC_ENABLE_INSTALL)
       install(TARGETS glslc_exe
    +    BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
         RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
     endif(SHADERC_ENABLE_INSTALL)
    

    glslang

    diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt
    index 2cf2899c..f84fdd2b 100644
    --- a/StandAlone/CMakeLists.txt
    +++ b/StandAlone/CMakeLists.txt
    @@ -50,11 +50,13 @@ endif(WIN32)
    
     if(ENABLE_GLSLANG_INSTALL)
         install(TARGETS glslangValidator EXPORT glslangValidatorTargets
    +            BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
                 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
         install(EXPORT glslangValidatorTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
    
         if(ENABLE_SPVREMAPPER)
             install(TARGETS spirv-remap EXPORT spirv-remapTargets
    +            BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
                 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
             install(EXPORT spirv-remapTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
         endif()
    

    Also here's the change to shader.rs

    diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs
    index f963c0c9..2e710cd0 100644
    --- a/crates/bevy_render/src/shader/shader.rs
    +++ b/crates/bevy_render/src/shader/shader.rs
    @@ -1,7 +1,6 @@
     use super::ShaderLayout;
     use bevy_asset::Handle;
    -use bevy_glsl_to_spirv::compile;
    -use std::{io::Read, marker::Copy};
    +use std::{marker::Copy};
     
     /// The stage of a shader
     #[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
    @@ -11,14 +10,14 @@ pub enum ShaderStage {
         Compute,
     }
     
    -impl Into<bevy_glsl_to_spirv::ShaderType> for ShaderStage {
    -    fn into(self) -> bevy_glsl_to_spirv::ShaderType {
    -        match self {
    -            ShaderStage::Vertex => bevy_glsl_to_spirv::ShaderType::Vertex,
    -            ShaderStage::Fragment => bevy_glsl_to_spirv::ShaderType::Fragment,
    -            ShaderStage::Compute => bevy_glsl_to_spirv::ShaderType::Compute,
    -        }
    -    }
    +impl Into<shaderc::ShaderKind> for ShaderStage {
    +   fn into(self) -> shaderc::ShaderKind {
    +       match self {
    +           ShaderStage::Vertex => shaderc::ShaderKind::Vertex,
    +           ShaderStage::Fragment => shaderc::ShaderKind::Fragment,
    +           ShaderStage::Compute => shaderc::ShaderKind::Compute,
    +       }
    +   }
     }
     
     fn glsl_to_spirv(
    @@ -26,10 +25,19 @@ fn glsl_to_spirv(
         stage: ShaderStage,
         shader_defs: Option<&[String]>,
     ) -> Vec<u32> {
    -    let mut output = compile(glsl_source, stage.into(), shader_defs).unwrap();
    -    let mut spv_bytes = Vec::new();
    -    output.read_to_end(&mut spv_bytes).unwrap();
    -    bytes_to_words(&spv_bytes)
    +    let mut compiler = shaderc::Compiler::new().unwrap();
    +    let mut options = shaderc::CompileOptions::new().unwrap();
    +    if let Some(shader_defs) = shader_defs {
    +        for def in shader_defs.iter() {
    +            options.add_macro_definition(def, None);
    +        }
    +    }
    +
    +    let binary_result = compiler.compile_into_spirv(
    +        glsl_source, stage.into(),
    +        "shader.glsl", "main", Some(&options)).unwrap();
    +
    +    binary_result.as_binary().to_vec()
     }
     
     fn bytes_to_words(bytes: &[u8]) -> Vec<u32> {
    
  9. MichaelHills commented on Aug 24, 2020

    @MichaelHills
    Contributor

    Stumbled across this issue in CMake https://gitlab.kitware.com/cmake/cmake/-/issues/20956 which suggests that the whole BUNDLE DESTINATION thing might be due to some CMake default that doesn't make sense when building libs, and I don't need to try and get BUNDLE DESINATION added to shaderc and glsl.

  10. naithar commented on Aug 24, 2020

    @naithar
    Contributor

    Basically atm I build my "game" as a static lib and then call out to it manually from in an ios xcode project.

    Godot works in same way, though it implements it's own main which gets used by iOS application.

    Obj-C can be used too, but this would require only main.mm file like this:

    @import UIKit;
    
    extern "C" void bevy_main(void);
    
    int main(int argc, char * argv[]) {
        bevy_main();
    }
    

    And additional values in Other C Flags in Build Settings: -fmodules -fcxx-modules.

    I've tested with 2d -> sprite.rs example, but got empty window.
    I guess asset loading would require some work for iOS, but correct (?) texture handle was returned Handle<Texture>(82f42690-2c58-4843-a88a-aa066583f97d), so I'm not sure.

    • Figure out why coreaudio-sys v0.2.5 panics during compile (that was why I had to disable audio)

    This PR (RustAudio/coreaudio-sys#33) seems to be addressing this issue, but I wasn't able to make it work even with this changes. But maybe it's just me as I don't really have much experience with rust.

  11. MichaelHills commented on Aug 24, 2020

    @MichaelHills
    Contributor

    @naithar oh cool glad to see someone else getting it working too. Yeah I didn’t get the sprite example working, I also assumed it was related to asset loading but I haven’t looked into that yet.

    Interesting I’ll try pulling that audio PR later to see if it works.

  12. MichaelHills commented on Aug 24, 2020

    @MichaelHills
    Contributor

    By the way were you able to get the simulator working? I’m still getting the issue with Target OS is incompatible: library was not compiled for the simulator but supposedly there should be simulator metal support gfx-rs/gfx#2873 so not sure yet what the problem with that is.

  13. naithar commented on Aug 24, 2020

    @naithar
    Contributor

    No, I've got some error about unsupported architecture from dependency. I'll try to look more into it after I figure out asset loading :)

    Godot uses 13.0 sdk version for simulator, since this the only simulator version supporting Metal. But while it does build, MoltenVK fails and application doesn't launch in the end.
    So cargo lipo might be using lower sdk version that actually required for bevy.

  14. MichaelHills commented on Aug 25, 2020

    @MichaelHills
    Contributor

    Looks like the ios audio support is still in-progress as per your link, I tried and failed to get that branch to work as well. I'll leave audio disabled for now and might have a try at getting the simulator going.

  15. 58 remaining items

  16. dvtkrlbs commented on Oct 7, 2020

    @dvtkrlbs

    The new version of rodio is now released. I am working on PR. (this helps with audio not working on macOS and ios)

  17. naithar commented on Oct 7, 2020

    @naithar
    Contributor

    I've made some changes to original @MichaelHills touch support diff here: In my fork
    I plan to make a PR if #334 wouldn't be moving anywhere if that's okay :)
    I'll also run some more test just to be sure that everything is working as intended.

  18. dvtkrlbs commented on Oct 11, 2020

    @dvtkrlbs

    Another problem is it takes a long time for a new version of rodio to release on crates.io. So even if these issues gets fixed you wont be able use them for a long time (rodio makes new releases for every 4 months or so) so you need to maintain your own bevy-audio (since crates.io crates cant use git dependencies).

  19. MichaelHills commented on Oct 11, 2020

    @MichaelHills
    Contributor

    Another problem is it takes a long time for a new version of rodio to release on crates.io. So even if these issues gets fixed you wont be able use them for a long time (rodio makes new releases for every 4 months or so) so you need to maintain your own bevy-audio (since crates.io crates cant use git dependencies).

    I haven't needed to modify Rodio. Does that mean we're ok? Or at worst can just use [patch.crates-io] to change the cpal version if there's a significant version bump.

  20. MichaelHills commented on Oct 17, 2020

    @MichaelHills
    Contributor

    I've made some changes to original @MichaelHills touch support diff here: In my fork
    I plan to make a PR if #334 wouldn't be moving anywhere if that's okay :)
    I'll also run some more test just to be sure that everything is working as intended.

    @naithar Looks like no movement on #334, want to put up yours? Or give some diffs so that #334 can be landed with original attribution, and then put up another PR for enhancements?

  21. naithar commented on Oct 17, 2020

    @naithar
    Contributor

    @MichaelHills yeah, seems like it. I'll rebase and make a PR soon.

  22. naithar commented on Oct 19, 2020

    @naithar
    Contributor

    Well, I found our problem! You need to disable XCode "Remove text metadata from PNG". I disabled everything though just to be sure... I guess the image loading library can't handle whatever XCode does to it.

    this shouldn't be required anymore after #693. Listing assets folder in Copy bundle resources is enough for assets to work. Tested with iOS device and macOS .app file.

    Also there is no need for a workaround for set_current_dir as PR seems to be solving this too.

  23. added
    O-iOSSpecific to the iOS mobile operating system
    on Oct 27, 2020
  24. francesca64 commented on Dec 2, 2020

    @francesca64

    Is there any interest in using cargo-mobile to simplify generating Xcode projects / building / running on device / etc?

  25. cart commented on Dec 2, 2020

    @cart
    MemberAuthor

    Medium-to-long term I might be interested in adopting higher level abstractions. Short term I'd rather keep it simple, encourage people to become familiar with the "native" mobile tooling, and maintain control over "official" templates. We will likely create an official bevy_template repo in the near future.

  26. alice-i-cecile commented on Apr 26, 2022

    @alice-i-cecile
    Member

    This now works!

  27. Rust-Ninja-Sabi commented on Sep 25, 2022

    @Rust-Ninja-Sabi

    Is there any tutorial about Bevy and ios today?

  28. added a commit that references this issue on Nov 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-Build-SystemRelated to build systems or continuous integrationC-FeatureA new feature, making something new possibleO-iOSSpecific to the iOS mobile operating system

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions