Xcode project template doesn't work
System Information
- Ogre Version: 2.3
- Operating System / Platform: macOS 11.6
- RenderSystem: Metal
- GPU: Radeon Pro 560X
Detailed description
The Xcode template in SDK/OSX/Xcode Templates/Xcode4/Project Templates/Ogre produces a broken project that can't find its files. I guess that shouldn't be too much of a surprise given the "Xcode4" in the path, when Xcode is at version 12. After I started fixing search paths and so forth, I found that the template files reference a deprecated header OgreRenderWindow.h, and requires a 3rd-party library called OIS. It would be great if there were an up to date macOS Xcode project template or starter project that uses only native functions other than Ogre, no SDL or OIS.
Hi!
I can't remember if it's in a working state (on macOS) but the sample Samples/2.0/Tutorials/Tutorial00_Basic should give you what you want (starter project without SDL, get a working window with only 217 lines), but we do recommend you study Tutorial01 through Tutorial06 (which relies on SDL) for a robust handling of the update loop.
And indeed I didn't even realize there was something under SDK/OSX/Xcode. That is extremely old and abandoned. We have to remove it.
Tutorial00_Basic is not in a working state on macOS, it crashes on launch. In a forum thread, you said:
macOS requires more specific/complex initialization thus I preferred to ignore it, because the sample is meant to be as simple as possible "get me a working window as fast as possible without any dependencies or too much code".
What's the crash call stack?
Call stack:
frame #0: 0x00007fff20355552 libsystem_platform.dylib`_platform_strlen + 18
* frame #1: 0x0000000103eb0675 Ogre`std::__1::char_traits<char>::length(__s=0x0000000000000000) at __string:372:53
frame #2: 0x000000010371b5f6 Ogre`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::nullptr_t>(this="", __s=0x0000000000000000) at string:841:19
frame #3: 0x00000001037170cd Ogre`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::nullptr_t>(this="", __s=0x0000000000000000) at string:839:88
frame #4: 0x0000000103719968 Ogre`-[OgreConfigWindowDelegate refreshConfigOptions](self=0x00006000038884e0, _cmd="refreshConfigOptions") at OgreConfigDialog.mm:230:39
frame #5: 0x000000010371966f Ogre`-[OgreConfigWindowDelegate init](self=0x00006000038884e0, _cmd="init") at OgreConfigDialog.mm:219:9
frame #6: 0x0000000103716ff0 Ogre`Ogre::ConfigDialog::initialise(this=0x0000600001cb5220) at OgreConfigDialog.mm:52:27
frame #7: 0x0000000103717129 Ogre`Ogre::ConfigDialog::display(this=0x0000600001cb5220) at OgreConfigDialog.mm:66:13
frame #8: 0x0000000103bf54ac Ogre`Ogre::Root::showConfigDialog(this=0x00007fd85250b6a0, aCustomDialog=0x0000000000000000) at OgreRoot.cpp:647:21
frame #9: 0x0000000102cdefe9 Sample_Tutorial00_Basic`main(argc=1, argv=0x00007ffeecf27318) at Tutorial00_Basic.cpp:166:16
In refreshConfigOptions, the problem occurs on the line
String selectedRenderSystemName = String([[[mRenderSystemsPopUp selectedItem] title] UTF8String]);
and I can see in the debugger that [mRenderSystemsPopUp selectedItem] is nil.
It sounds like the Metal RenderSystem didn't get loaded at all. Is there an Ogre.log generated? Could you upload it?
Where would I look for Ogre.log?
I suspect it was trying to put Ogre.log somewhere it didn't have permission to write. I changed the writeAccessFolder string to a legitimate location, and got an Ogre.log.
Hi thanks!
And the same is happening with the plugins.cfg file (which tells which plugins to load and their locations, including RenderSystems)
It couldn't find it so no RenderSystems loaded leads to the crash, either because the relative path is wrong for mac, or because the file is not being included into the bundle
You're right, the file is not being included in the bundle, but even if I fix that, it still doesn't work, because the sample isn't looking in the bundle for the plugins.cfg file. It's just looking in the current working directory, wherever the heck that is. It's awkward to fix that without using any Objective-C, but I'll see what I can do.
We provide some helpers which should help you on this issue (source code)
Yes, that helps. If I replace the line
const String pluginsFolder = "./";
with
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
const String pluginsFolder = macBundlePath() + "/Contents/Resources/";
#else
const String pluginsFolder = "./";
#endif
then it gets past the configuration dialog before crashing. The new crash call stack:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x000000010faf87cc Ogre`Ogre::VaoManager::getFrameCount(this=0x2020202020000000) at OgreVaoManager.h:522:54
frame #1: 0x000000010fc0d6bc Ogre`Ogre::GpuResource::GpuResource(this=0x0000600000ae8628, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow")) at OgreGpuResource.cpp:56:37
frame #2: 0x000000011015ea9d Ogre`Ogre::TextureGpu::TextureGpu(this=0x0000600000ae8620, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow"), textureFlags=16899, initialType=Type2D, textureManager=0x00007fad76074400) at OgreTextureGpu.cpp:57:9
frame #3: 0x00000001150a4c06 RenderSystem_Metal`Ogre::MetalTextureGpu::MetalTextureGpu(this=0x0000600000ae8620, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow"), textureFlags=16899, initialType=Type2D, textureManager=0x00007fad76074400) at OgreMetalTextureGpu.mm:52:9
frame #4: 0x00000001150a7972 RenderSystem_Metal`Ogre::MetalTextureGpuRenderTarget::MetalTextureGpuRenderTarget(this=0x0000600000ae8620, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow"), textureFlags=16899, initialType=Type2D, textureManager=0x00007fad76074400) at OgreMetalTextureGpu.mm:409:9
frame #5: 0x00000001150aa9e6 RenderSystem_Metal`Ogre::MetalTextureGpuWindow::MetalTextureGpuWindow(this=0x0000600000ae8620, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow"), textureFlags=16899, initialType=Type2D, textureManager=0x00007fad76074400, window=0x00006000001dc000) at OgreMetalTextureGpuWindow.mm:49:9
frame #6: 0x00000001150aaad4 RenderSystem_Metal`Ogre::MetalTextureGpuWindow::MetalTextureGpuWindow(this=0x0000600000ae8620, pageOutStrategy=Discard, vaoManager=0x2020202020000000, name=(mHash = 1169432017, mDebugString = "RenderWindow"), textureFlags=16899, initialType=Type2D, textureManager=0x00007fad76074400, window=0x00006000001dc000) at OgreMetalTextureGpuWindow.mm:52:5
frame #7: 0x00000001150a9f3b RenderSystem_Metal`Ogre::MetalTextureGpuManager::createTextureGpuWindow(this=0x00007fad76074400, window=0x00006000001dc000) at OgreMetalTextureGpuManager.mm:158:25
frame #8: 0x00000001150ad3b9 RenderSystem_Metal`Ogre::MetalWindow::_initialize(this=0x00006000001dc000, textureGpuManager=0x00007fad76074400) at OgreMetalWindow.mm:342:43
frame #9: 0x000000011508a416 RenderSystem_Metal`Ogre::MetalRenderSystem::_createRenderWindow(this=0x00007fad86010800, name="Tutorial 00: Basic", width=1, height=1, fullScreen=false, miscParams=0x0000000000000000)0> > > const*) at OgreMetalRenderSystem.mm:542:14
frame #10: 0x0000000115089b6f RenderSystem_Metal`Ogre::MetalRenderSystem::_initialise(this=0x00007fad86010800, autoCreateWindow=true, windowTitle="Tutorial 00: Basic") at OgreMetalRenderSystem.mm:491:26
frame #11: 0x000000010ff85147 Ogre`Ogre::Root::initialise(this=0x00007fad98005410, autoCreateWindow=true, windowTitle="Tutorial 00: Basic", customCapabilitiesConfig="") at OgreRoot.cpp:802:40
frame #12: 0x000000010f0661b3 Sample_Tutorial00_Basic`main(argc=1, argv=0x00007ffee0ba0318) at Tutorial00_Basic.cpp:177:28
Ok I don't recognize the error and it sounds like the VaoManager pointer passed along via constructors to GpuResource is either nullptr or corrupted (possibly corrupted because it says this = 0x2020202020000000 which looks very suspicious). I'll have to check it out myself.
Is there any chance you mixed a Debug DLL (dynlib) of MetalRenderSystem with a Release version of OgreMain (or viceversa)?
No, I've never built Release versions of any of the Ogre libraries.
Something I don't understand is happening in the constructor of MetalTextureGpuManager. A proper VaoManager pointer is passed in to the constructor, passed on to the constructor of the base class TextureGpuManager, and recorded in the member variable mVaoManager, but later in the MetalTextureGpuManager constructor, that member variable has the wrong value.
Something I don't understand is happening in the constructor of
MetalTextureGpuManager. A properVaoManagerpointer is passed in to the constructor, passed on to the constructor of the base classTextureGpuManager, and recorded in the member variablemVaoManager, but later in theMetalTextureGpuManagerconstructor, that member variable has the wrong value.
That can happen because:
- Code and binaries are out of sync. i.e. try building "MetalRenderSystem" project and "OgreMain" (or just building "ALL" project), or just clean/delete all and start again
- Somehow NDEBUG creeped in, and is being inconsistent between MetalRenderSystem and OgreMain projects; leading to different definitions of
OGRE_DEBUG_MODE
Huh, I don't know what happened, but you're right... I just deleted all the frameworks and rebuilt them, and now I get past that error. Now I get a new error,
OGRE EXCEPTION(6:FileNotFoundException): Data folder provided contains no valid template shader files. Did you provide the right folder location? Check you have the right read pemissions. Folder: /Volumes/Work/non-repo-libraries/Ogre-build/bin/Debug/Sample_Tutorial00_Basic.app/Contents/Resources/Hlms/Unlit/Metal in Hlms::Hlms at /Volumes/Work/git-repos/ogre/OgreMain/src/OgreHlms.cpp (line 460)
I suppose I just need to copy some stuff into the bundle. I'll play with that tomorrow. Thanks for all your help.
Ah yeah that error means that either rootHlmsFolder was pointing to the wrong place, or the files are not copied (or copied to the wrong place)
Having fixed that error, the program hangs. If I turn on Undefined Behavior Sanitizer, I see some log messages:
/Volumes/Work/git-repos/ogre/Components/Hlms/Pbs/src/OgreHlmsPbs.cpp:2031:71: runtime error: member call on null pointer of type 'Ogre::CompositorShadowNode'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Volumes/Work/git-repos/ogre/Components/Hlms/Pbs/src/OgreHlmsPbs.cpp:2031:71 in
/Volumes/Work/git-repos/ogre/OgreMain/include/Compositor/OgreCompositorShadowNode.h:280:30: runtime error: member call on null pointer of type 'const Ogre::CompositorShadowNode *'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Volumes/Work/git-repos/ogre/OgreMain/include/Compositor/OgreCompositorShadowNode.h:280:30 in
OK I pushed a fix for the UB bug. Thanks!
But I don't think that was the cause of your crash. Is the callstack there? (when sanitizer is off, or after pulling my fix)
At this point I don't have a crash, but a hang. Using the Time Profiler in Instruments, the heaviest stack trace (after pulling your fix) is:
25 Sample_Tutorial00_Basic 25196.0 main /Volumes/Work/git-repos/ogre/Samples/2.0/Tutorials/Tutorial00_Basic/Tutorial00_Basic.cpp:213
24 Ogre 22697.0 Ogre::Root::renderOneFrame() /Volumes/Work/git-repos/ogre/OgreMain/src/OgreRoot.cpp:1128
23 Ogre 19361.0 Ogre::Root::_updateAllRenderTargets() /Volumes/Work/git-repos/ogre/OgreMain/src/OgreRoot.cpp:1554
22 Ogre 16902.0 Ogre::CompositorManager2::_update() /Volumes/Work/git-repos/ogre/OgreMain/src/Compositor/OgreCompositorManager2.cpp:705
21 RenderSystem_Metal 16890.0 Ogre::MetalRenderSystem::updateCompositorManager(Ogre::CompositorManager2*) /Volumes/Work/git-repos/ogre/RenderSystems/Metal/src/OgreMetalRenderSystem.mm:2720
20 Ogre 16787.0 Ogre::CompositorManager2::_updateImplementation() /Volumes/Work/git-repos/ogre/OgreMain/src/Compositor/OgreCompositorManager2.cpp:783
19 Ogre 15066.0 Ogre::CompositorWorkspace::_update(bool) /Volumes/Work/git-repos/ogre/OgreMain/src/Compositor/OgreCompositorWorkspace.cpp:835
18 Ogre 14899.0 Ogre::CompositorNode::_update(Ogre::Camera const*, Ogre::SceneManager*) /Volumes/Work/git-repos/ogre/OgreMain/src/Compositor/OgreCompositorNode.cpp:820
17 Ogre 14809.0 Ogre::CompositorPassScene::execute(Ogre::Camera const*) /Volumes/Work/git-repos/ogre/OgreMain/src/Compositor/Pass/PassScene/OgreCompositorPassScene.cpp:298
16 Ogre 6903.0 Ogre::Viewport::_updateRenderPhase02(Ogre::Camera*, Ogre::Camera const*, unsigned char, unsigned char) /Volumes/Work/git-repos/ogre/OgreMain/src/OgreViewport.cpp:272
15 Ogre 6900.0 Ogre::Camera::_renderScenePhase02(Ogre::Camera const*, unsigned char, unsigned char, bool) /Volumes/Work/git-repos/ogre/OgreMain/src/OgreCamera.cpp:408
14 Ogre 6829.0 Ogre::SceneManager::_renderPhase02(Ogre::Camera*, Ogre::Camera const*, unsigned char, unsigned char, bool) /Volumes/Work/git-repos/ogre/OgreMain/src/OgreSceneManager.cpp:1468
13 RenderSystem_Metal 3452.0 Ogre::MetalRenderSystem::executeRenderPassDescriptorDelayedActions() /Volumes/Work/git-repos/ogre/RenderSystems/Metal/src/OgreMetalRenderSystem.mm:1152
12 RenderSystem_Metal 3408.0 Ogre::MetalRenderSystem::executeRenderPassDescriptorDelayedActions(bool) /Volumes/Work/git-repos/ogre/RenderSystems/Metal/src/OgreMetalRenderSystem.mm:1046
Ah! Thanks!
Are you able to submit your changes to get Tutorial 00 to this stage? That'd make my work easier to check this issue
Not sure what you mean by "submit your changes", in what form?
Either a diff or pull request. If you think the changes aren't good enough (ie. has some hardcoded stuff) posting a patch here is fine
Aside from my change to the pluginsFolder path that I gave earlier in this thread, all my changes were in the Xcode project, not in the source. I guess that Xcode project was generated by Cmake, and I am not sufficiently knowledgeable about Cmake to figure out what changes to Cmake files would be necessary to make the appropriate changes in the Xcode project file. But I can tell you what I did to the project:
- In the Sample_Tutorial00_Basic target, under the Build Phases tab, added a "Copy Bundle Resources" phase.
- In that phase, added references to the folders Hlms and 2.0 and the files plugins.cfg and resources2.cfg from the Sample_Tutorial00_Basic group in the project navigator hierarchy.
- Added a new Run Script build phase, with this content:
SRCPATH=$OGRE_SDK_ROOT/lib/macosx/$CONFIGURATION
DSTPATH=$CONFIGURATION_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH
/usr/bin/ditto "$SRCPATH/Ogre.framework" "$DSTPATH/Ogre.framework"
/usr/bin/ditto "$SRCPATH/OgreHlmsPbs.framework" "$DSTPATH/OgreHlmsPbs.framework"
/usr/bin/ditto "$SRCPATH/OgreHlmsUnlit.framework" "$DSTPATH/OgreHlmsUnlit.framework"
/usr/bin/ditto "$SRCPATH/OgreOverlay.framework" "$DSTPATH/OgreOverlay.framework"
/usr/bin/ditto "$SRCPATH/OgreSceneFormat.framework" "$DSTPATH/OgreSceneFormat.framework"
/usr/bin/ditto "$SRCPATH/Plugin_ParticleFX.framework" "$DSTPATH/Plugin_ParticleFX.framework"
/usr/bin/ditto "$SRCPATH/RenderSystem_Metal.framework" "$DSTPATH/RenderSystem_Metal.framework"
That last step might not be required to be able to run the app under the Xcode debugger, but is needed to run the app independently.
OK I took a look at the sample. I pushed a fix for the initial crashes you found.
However I got to the same point as you (the app "freezes" doing nothing). Actually it works fine, but the render loop iterates without displaying anything on screen
After a quick inspection the problem is about window handling. On macOS we have been relying on SDL to handle events and windowing.
Without SDL, there Ogre creates OgreMetalWindow creates an NSView and an NSWindow but there is no NSWindowController (or at least I believe that's the problem)
Ogre is currently not providing one out of the box and the sample is not providing one either. On iOS the samples provide an UIViewController in TutorialViewController.mm, but there is nothing being done on macOS.
Thus that's why it's not working... there's missing code, that hasn't been written yet. I'm no macOS windowing expert; thus perhaps you or someone else is better suited than me to fix it. Help is appreciated.
Thanks, I'll see what I can do. By the way, have you considered turning on GitHub's Discussions tab? Personally I like that better than going elsewhere for forums.
How did you come to the conclusion that a window controller was needed? I did a bit of testing in Tutorial01, one of the samples that works with SDL. At least as of the end of MetalWindow::create, the window provided by SDL does not have a window controller.
What looks more questionable to me is that WindowEventUtilities::messagePump() compiles down to nothing on macOS.
How did you come to the conclusion that a window controller was needed? I did a bit of testing in Tutorial01, one of the samples that works with SDL. At least as of the end of MetalWindow::create, the window provided by SDL does not have a window controller.
What looks more questionable to me is that WindowEventUtilities::messagePump() compiles down to nothing on macOS.
Based on example code on the internet it looks like the missing piece. But again like I said I have very little experience with NSWindow in general, thus I could be wrong.
See pull request #223