StOneDOes Posted Tuesday at 06:45 AM Share Posted Tuesday at 06:45 AM Can we please have a way for multithreaded resource loading eg. models, textures, sounds. I think it will get quite slow when stacking up a lot of resources to be loaded on the main thread, not to mention that you can't render anything while this is occurring. Ideally, a thread pool class would be useful for this. 1 Quote Link to comment Share on other sites More sharing options...
Josh Posted Tuesday at 03:58 PM Share Posted Tuesday at 03:58 PM If you are loading content like that, wouldn't the bottleneck be the hard drive read speed, in which case multiple threads would make it slower? 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
StOneDOes Posted Thursday at 08:14 AM Author Share Posted Thursday at 08:14 AM I'm not sure if I misunderstand what you mean "like that" - there's several resources that are needed to be loaded on startup that simply wouldn't do during gameplay or you would see clear hiccups in play, for example when a player picks up a weapon for the first time. And naturally, you load all resources for a map when you want to enter that map, but you don't want the main thread locked up, and game unresponsive during that time. The hard drive is not the bottleneck, its the fact that the main thread is loading everything. Ideally, the main thread will sit idly by, showing some kind of loading animation, while the thread pool is loading all required resources. You could provide a non-fool-proof mechanism under which the developer provides the start point and end point essentially for loading, in which time it's not safe to render/play those given resource, so you can avoid mutex locks all over the place in your resource wrapper classes. Quote Link to comment Share on other sites More sharing options...
Josh Posted Thursday at 03:17 PM Share Posted Thursday at 03:17 PM 7 hours ago, StOneDOes said: Ideally, the main thread will sit idly by, showing some kind of loading animation, while the thread pool is loading all required resources. That's basically how the rendering thread works right now. If the main thread stalls, the rendering thread just keeps drawing frames. You can use a shader to display a spinning indicator for a loading screen while the next level is loading. 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
StOneDOes Posted Friday at 07:58 AM Author Share Posted Friday at 07:58 AM Right, but if I were to click on the window while this loading was taking place, the window would go grey and say the program is unresponsive, wouldn't it? Quote Link to comment Share on other sites More sharing options...
Josh Posted Friday at 04:15 PM Share Posted Friday at 04:15 PM Yes. Another option might be to use a callback with the scene load function and periodically check for window events in the callback. It would probably even be fine to create a separate thread and load the scene on that thread, as long as you did not call any commands other than PeekEvent/WaitEvent in the main thread while that was running. Something like this: while (PeekEvent()) WaitEvent(); // clear out events auto thread = CreateThread(std::bind(&LoadScene, mapfile)); // create loading thread while (thread->GetState() != THREAD_FINISHED) { while (PeekEvent()) WaitEvent(); // process events so window keeps responding Sleep(10); } If you have any event hooks that execute 3D commands while the loading thread is running, it could cause big problems, so make sure you aren't doing anything based on keyboard input, for example, other than just setting some values like jumpkeypressed = true. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
StOneDOes Posted Saturday at 05:49 AM Author Share Posted Saturday at 05:49 AM 13 hours ago, Josh said: If you have any event hooks that execute 3D commands while the loading thread is running, it could cause big problems, so make sure you aren't doing anything based on keyboard input, for example, other than just setting some values like jumpkeypressed = true. So we could use this same logic, but instead of just using a single thread; a thread pool. While we know we are in loading state, we simply just do not do anything involving resources, otherwise we would probably expect issues. Is your under-the-hood resource manager thread safe? If it is I can test this myself. Quote Link to comment Share on other sites More sharing options...
Josh Posted Saturday at 03:43 PM Share Posted Saturday at 03:43 PM 9 hours ago, StOneDOes said: Is your under-the-hood resource manager thread safe? If it is I can test this myself. No, definitely not. If you start creating entities in the world on different threads it will cause very bad problems. Even if your tests work fine, it is going to eventually start crashing. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
StOneDOes Posted yesterday at 12:23 AM Author Share Posted yesterday at 12:23 AM Right, so what would be the chances of you putting this on the to-do list? Because this is a big concern for me; Right now I have (I would say not a large amount) of different resources loaded just after the map has been loaded (I do have 2 high quality weapons), and it is taken almost 35 seconds in debug mode. I haven't written my cmakelists for release mode yet so I don't have a metric on that, but given that the map would be not even 10% done; it is a bit of a worry, and I haven't added any LODs to the existing models that I have (which could cause longer load times). In Battlefield 4, it takes me less than 20 seconds to join a full server on a large conquest map. Now I know its not fair to compare a work in progress engine to arguably one of (if not) the best game engines ever made, but I'm just trying to put loading time into perspective. And I don't think it would be difficult to do, although obviously I can't see your implementation. I am more than happy to provide an efficient thread pool for this, but I can't handle the thread saftey side. Just to note I have a AMD Ryzen 9 3900X processor, and wouldn't expect people to require something newer than this to play my game. Quote Link to comment Share on other sites More sharing options...
Josh Posted yesterday at 12:54 AM Share Posted yesterday at 12:54 AM I do not plan on attempting to create entities on another thread because it would cause an enormous amount of problems. Most multiplayer games have a pretty much static world and don't require the flexibility our entity system provides. If I were to implement something like what BF4 is probably doing, it would require a major tradeoff because things you might take for granted right now would suddenly be impossible. It's not really a matter of one engine being better than the other, it's just that BF4 is probably highly specialized for one game, and compared to that my engine tends to favor flexibility and ease of use. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted yesterday at 12:59 AM Share Posted yesterday at 12:59 AM 35 minutes ago, StOneDOes said: and it is taken almost 35 seconds in debug mode How long does it take in release mode? I think a better direction to look at in the future might be seeing if scene load times can be optimized at all. That's usually much easier than a complicated multithreaded system that will probably not work very well. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
StOneDOes Posted yesterday at 01:40 AM Author Share Posted yesterday at 01:40 AM I mentioned BF4 just as an example of me saying, this is how much stuff is in that world/map and it doesn't take long, and its a very nonstatic / alive world. I don't think it would be a stretch to say that most modern game engines would use multiple threads for resource loading, or at least provide a means to do so. One other suggestion that I have is, something that would hopefully be rather easy; If you were to provide some kind of function eg. Entity::CreateModelUnmanaged(). It takes a path to the file on disk loads it, and simply returns the new model, and does not touch your system or resource manager whatsoever. Then I can run this on multiple threads, store a whole collection of models on my end, and then when I'm done, on the main thread, I use some other function like World::ManageMyModel() which takes the shared pointer that I received earlier, and basically copies it into your resource manager, just like the existing CreateModel() function would do. That way I handle all the thread safety, and the engine remains hypothetically untouched? Admittedly, the longest load times are caused by weapons that are not actually in the map (or at least not yet), rather given to the player, so something like this would be super useful to do say on game startup. As for how long release mode takes; I'll get back to you when I finish writing the release mode cmakelists ... I've been putting that off for a while Quote Link to comment Share on other sites More sharing options...
Josh Posted yesterday at 02:23 AM Share Posted yesterday at 02:23 AM Theoretically LoadModel() with the LOAD_UNMANAGED flag in a separate world might be safe, but I would not recommend this. If there is a big difference between the release and debug load speeds, that indicates to me STL is likely the cause. I think we are better off identifying bottlenecks and targeting those. The problem resource loading stuff that could be multithreaded is likely already not to be a problem, just look how fast textures load in the latest builds of the editor. Likewise, mesh data is really unlikely to be forming a bottleneck unless STL is causing one, in which case the best solution would be our own resizable array class to replace STL vector. I had to write my own sorting code in some of the terrain system because the STL version was too slow in debug builds. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.