Native GML Multithreading in GameMaker - No DLLs/Networking

GMWolf

aka fel666
That's pretty rough. If someone wanted to improve/expand things, I would have thought they'd be supportive that you are pushing the engine to greater limits.
If they hadn't said no, then everyone would have array literals, argument declarations (no more need for argument 0, argument1...), More pragmas, preprocessor directives...
I even designed the tool so anyone could write a plugin.
The one caveat is that it still had to look like proper GML, so it's not possible to add new syntax, just modify or extend existing syntax.

I'm trying to do the same with GMS2 now but so far no such luck. GMS2 would allow new syntax though, as the IDE still launches compiler when it thinks there is an error.


Sorry for hijack.
 
M

MishMash

Guest
The way i've looked at this is that there isn't actually any decompiling or reverse engineering of GMs own internal code, it is simply the addition of code, in much the same way as a DLL would work. There was even a thread https://forum.yoyogames.com/index.php?threads/get_function_address-function_name.42745/ discussing the ability to re-add get_function_address() which would allow you to achieve exactly what this little trick does, only via a DLL. As Russel mentioned (and as I had said about where threading could break things) is that you have to consider the context for certain function calls.

When looking at this threading extension and consider it only from an algorithmic point of view, that is, using it to simply perform tasks without extensive use of internal GM systems, is it effectively the same as if you were to write the code in a DLL. However, for the sake of efficiency, we can bridge that gap.

I also made this topic a few months ago: https://forum.yoyogames.com/index.php?threads/custom-c-code-in-yyc.4612/ which was to facilitate a means of systematically integrating your own DLL code directly into the exe so as to avoid the overhead in the DLL function call, yielding huge speed ups.

When looking at the sorts of code you are working with, in both cases, the only code being modified is the C++-generated version of MY OWN gml code. The fundamental way GM works isn't being changed, only the code that is built, therefore I would assume that this isn't really reverse engineering. Everything I have discussed in these topics CAN and HAS been achieved with DLLs, however, DLLs make this process less efficient and hard to work with.

What I think would be an interesting end-goal is if the conversation in general could perhaps motivate an improvement for the GM extension system to support native extensions (that is, extensions with code that can be directly integrated into your compiled project, rather than having to separately link through a DLL). If it is possible for us to make these things work without any major fundamental change to GameMaker, other than a few lines of C++ in the right place, it stands to reason that an overall system like this wouldn't be ridiculously difficult to implement. It is a shame however that there cannot be more windows-specific functionality, as I feel that is one of the major barriers to progression. Perhaps its to do with my lack of mobile perception, but I generally feel that Windows is the most dominant platform when it comes to use of GM, both for fun and commercially.
 
I

icuurd12b42

Guest
agreed. in the end the yyc compiles, with a 3rd party, a binary specific to your code, excluding parts not used if I remember. There is no danger in this as opposed if you would for example change a dll the runner would use

For one thing though, you are rubbing Yoyo nose in the fact they been reluctant to add async (user) code, they have their reason for not having it in but this shows it's not really that much of an effort, at least in the yyc, to add... and IMHO they should really consider adding this to the core...
 
L

Lonewolff

Guest
Still comes under 'modify and creating derivative works' though unfortunately.

I'd tag one of the boys in and see if they give you the ok. You'll know right away then, what YYG stance is on it.
 

GMWolf

aka fel666
agreed. in the end the yyc compiles, with a 3rd party, a binary specific to your code, excluding parts not used if I remember. There is no danger in this as opposed if you would for example change a dll the runner would use

For one thing though, you are rubbing Yoyo nose in the fact they been reluctant to add async (user) code, they have their reason for not having it in but this shows it's not really that much of an effort, at least in the yyc, to add... and IMHO they should really consider adding this to the core...
This isn't the only thing that we have been asking for in ages that would require minimal work to get implemented. A lot of language features already have all the groundwork to get going, like anonymous scripts, inline accessors, etc.
I think it would be far better for YoYo to focus on improving the engine rather than porting it to every platform out there. A better language will mean more add ins, libraries, etc which will make development faster and grow the userbase.
Certainly more than the switch will. I doubt many new users will come because of switch support.
Still comes under 'modify and creating derivative works' though unfortunately.

I'd tag one of the boys in and see if they give you the ok. You'll know right away then, what YYG stance is on it.
How could you?
 
I

icuurd12b42

Guest
Still comes under 'modify and creating derivative works' though unfortunately.

I'd tag one of the boys in and see if they give you the ok. You'll know right away then, what YYG stance is on it.
If you follow this reasoning, you would not be allowed to change the default shader include, which you can...

Reverse engineering is perfectly fine as long as the derivative work does not endanger the profit of the original publisher of said work.

If my company want to streamline the development process of a project by fiddling with the engine's core, allowing me for example to call the compiler from the command line... I can. the final work does not remove any profits from yoyo since the final work is my own game.
 
L

Lonewolff

Guest
If you follow this reasoning, you would not be allowed to change the default shader include, which you can...
If you were given permission to do this, then not a problem.

Reverse engineering is perfectly fine as long as the derivative work does not endanger the profit of the original publisher of said work.
That's not true at all.

If my company want to streamline the development process of a project by fiddling with the engine's core, allowing me for example to call the compiler from the command line... I can. the final work does not remove any profits from yoyo since the final work is my own game.
Again, you agreed to a EULA by saying that you would not do this.
 
I

icuurd12b42

Guest
If you were given permission to do this, then not a problem.



That's not true at all.



Again, you agreed to a EULA by saying that you would not do this.
Again, reverse engineering, hacking and other modification for your project is legal. be it you say you won't do it because the eula asks you not to, does not make it law. It is the moment you stand to profit at the detriment of the original company that makes it unlawful.

You can change the oil filter on your car with a better solution if you want to. no company can stop you. same point, simplified. just because something is in a EULA does not mean it's binding. There is a note about approval of these in the eula, just in case such thing is justifiable.
 
L

Lonewolff

Guest
Again, reverse engineering, hacking and other modification for your project is legal.
The moment you hit 'I agree' to the installer, the EULA it becomes a legally binding agreement.


It is the moment you stand to profit at the detriment of the original company that makes it unlawful.
As I said 'not true'...

What metric do you use to determine this?

If someone comes along and sees that you have made modifications to GM and then they say 'this cant do that out of the box?'. They walk away and use another engine, this immediately impacts profits on the product.

Not to mention people thinking 'Why isn't YYG making this a core feature?'. Then they think less of YYG, which then impacts reputation and product sales accordingly.


You can change the oil filter on your car with a better solution if you want to. no company can stop you. same point, simplified. just because something is in a EULA does not mean it's binding
You can change the oil whenever you like. It's a consumable, just like petrol.

As soon as you start making modifications to the engine it becomes unlawful - EPA legislation, insurance, liability.
 
I

icuurd12b42

Guest
"There is a note about approval of these in the eula, just in case such thing is justifiable."
You removed this...
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
it's not really that much of an effort, at least in the yyc, to add... and IMHO they should really consider adding this to the core...
Things are rarely as simple as they seem with software development.

Although I couldn't even say that they seem simple here because it is not known which functions are thread-safe and which aren't. And what's more fun than dealing with access violations because of untimely resource access between threads
 
L

Lonewolff

Guest
"There is a note about approval of these in the eula, just in case such thing is justifiable."
You removed this...
Exactly. Do you see the written approval from YYG yet?

I'm not sure that are reading any of my posts, just picking and choosing what you want to see.

I said earlier tag Mike or Russ and see if they are happy with this. I can't see why they wouldn't be, but I am not a YYG representative.

Poor @GMWolf allready had his efforts knocked in the head though by YYG.
 
M

MishMash

Guest
Just wanted to add that the theme of this topic was not intended to rub YYG up the wrong way, I can fully understand why threading isn't a normal feature, whether it be platform dependency, or just the wealth of bugs and conditions that would need to be considered.

Though on the note of the Eula, regarding derivative work and "They walk away and use another engine, this immediately impacts profits on the product.", bear in mind that DLLs and extensions somewhat fall into this category too, where do you draw the line? Certain features that are missing from the core engine are implemented by others. If you think about complex extensions like that video playing one, that is the sort of thing that isn't natively supported, but that is a completely valid extension. In fact, i'd say the opposite can be true in some cases.
Lets say there were people who had disregarded something as being possible and have gone elsewhere may have changed their mind if they knew there was atleast some way to achieve the results, however ugly it may be.

I guess the only way to know for sure is to ask @rwkay and @Mike whether this is okay. Or am I breaking the Eula by messing around with this stuff (editing generated C++ that is)? Is it something that I would be justified in doing on my own for the benefit of my own project?

Let me add again that I love what GM is, there is a reason why I use it as my engine of choice, but I do also enjoy pushing it to its absolute limits, and proving just how powerful the setup can be, whilst being able to keep the massive ease-of-use benefits that make it so good!
 
Last edited by a moderator:
I

icuurd12b42

Guest
Things are rarely as simple as they seem with software development.

Although I couldn't even say that they seem simple here because it is not known which functions are thread-safe and which aren't. And what's more fun than dealing with access violations because of untimely resource access between threads
well he added a threaded script execute in there. he could probably add mutex and semaphore functions too which would be better than what I stated in post 2 for synchronisation. again, as long as nothing is accessing the data being created/modified but the thread doing it, thing are relatively safe
 

DukeSoft

Member
Oh wow! I'm going to try this in 2 games I'm working on;
1) my Shoot 'm Up - I'll implement it in the level loading, which loads files / buffers and sprites / textures. Would be nice to have quicker loading times - and this is a good testcase as it touches quite a few internals from a thread.
2) a voxel game which generates both vertex buffers and big grids / other data structures on the fly (I currently limit the generation to like 10 chunks / step to keep the FPS up.) - This would be a MASSIVE improvement for this game.

If the solution is really this simple.... Wow.

Will get back with results later today. Sure hope YYG doesn't have any trouble with this (I don't think they do, because you clearly stated its not officially supported).
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
It messed with the GM compiler so I asked if they where ok with me releasing it..and if it was tevhntechni against the EULA.
I should not have asked.
I feel like I both want and don't want to know what did you do that it required messing with compiler directly
 

GMWolf

aka fel666
I feel like I both want and don't want to know what did you do that it required messing with compiler directly
Well I wasn't really messing with the compiler it self.
I just man in the Middled it.
GM would launch my program, that would do the preprocessing before calling the compiler itself.
All the "messing" that was required was a registery tweak.

I have tried this again in GMS2 but I think that Igor and the compiler are both crypto signed so I can't man in the middle it anymore.
 

kupo15

Member
Sorry for bringing my question back up after our nice conversation on it. I have a simple (I think) question I would like to follow up on regarding this gif where you are drawing and doing code. You said that using the second thread for loading and prefetching/flushing is not a good thing but this gif is using another thread for drawing...or is it the main thread that is drawing and the second thread that is moving it?

My question: Is it not possible or good with your method to have the main thread be used for loading, prefetching/flushing to avoid the issues you talked about and use the second thread to draw textures that have already been loaded in vram?
 
M

MishMash

Guest
Sorry for bringing my question back up after our nice conversation on it. I have a simple (I think) question I would like to follow up on regarding this gif where you are drawing and doing code. You said that using the second thread for loading and prefetching/flushing is not a good thing but this gif is using another thread for drawing...or is it the main thread that is drawing and the second thread that is moving it?

My question: Is it not possible or good with your method to have the main thread be used for loading, prefetching/flushing to avoid the issues you talked about and use the second thread to draw textures that have already been loaded in vram?
I don't recall the exact nature of the comment, however when working with DirectX 9, You should NOT do any resource loading or graphics work in anything other than the main thread, otherwise you could hit memory race conditions. This is because in DirectX9, the main thread is what communicates with the GPU. Resource loading in a separate thread can also be an issue because there is nothing that can be done to alter the way GM internals work. As we do not know exactly what GM functions do, or where their definitions are created

To extend, it is my personal opinion that in order to avoid any messy-ness or chance of problems, this method should only be used for algorithmic optimisations. That is, algorithms that perform an action on a datastructure in the background whilst nothing else is meddling. This can be for map generation, AI processing, pathfinding calculations, or in the case of loading, data decoding/formatting. (So you can load files in quickly using buffers, and then offload any complex analysis to the side threads). Equally though, they shouldn't be used in conjunction with any engine functions such as ones to play audio, create instances, create datastructures or the like, because this could result in a race condition.

The example gif that you shared was simply the modification of X/Y positions and the polling of keyboard input in the secondary thread, with the rendering happening in the main thread.
 

kupo15

Member
The example gif that you shared was simply the modification of X/Y positions and the polling of keyboard input in the secondary thread, with the rendering happening in the main thread.
Ok I was afraid the secondary thread was used for cpu calculations with changing the position instead of drawing. That's too bad. Could this limitation be lifted with Dx11 or a future DirectX if they have other threads also communicate with the GPU or is this never possible because of how GM works?
 
M

MishMash

Guest
Ok I was afraid the secondary thread was used for cpu calculations with changing the position instead of drawing. That's too bad. Could this limitation be lifted with Dx11 or a future DirectX if they have other threads also communicate with the GPU or is this never possible because of how GM works?
You would need to implement the API yourself for it to be possible, regardless of what GM does, unless you have access to GMs internal resource structure (which is the main thing we want to hold its integrity), its not possible. Though is loading really that much of an issue for you? How much are you loading? Or is it just to prevent micro-stutter?

You can make it work for model loading, by preallocating a buffer, loading first into a buffer, then creating a vertex buffer from that buffer in the main thread.
 

kupo15

Member
You would need to implement the API yourself for it to be possible, regardless of what GM does, unless you have access to GMs internal resource structure (which is the main thing we want to hold its integrity), its not possible. Though is loading really that much of an issue for you? How much are you loading? Or is it just to prevent micro-stutter?

You can make it work for model loading, by preallocating a buffer, loading first into a buffer, then creating a vertex buffer from that buffer in the main thread.
Mainly for a pleasant experience as currently it takes around 3 seconds of loading for a single character and there is going to be two separate characters loaded at once max. This doesn't include loading times of stage backgrounds, gfx and audio stuff. Would be nice to load the character as you select it in the background to avoid any interruption in the flow of menus and to avoid loading it all at one time. Or loading during a stage transition.

When you say model loading, that method also works for 2d and not limited to 3d models? I can achieve the above goal with this method? I just learned about buffers, I need to learn about vertex buffers
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
RE: EULA concerns... If you want to know the exact legal position on whether this can or cannot be done based on the current EULA, you really should file a support ticket with YYG and ask. None of the staff here are lawyers, and none of the YYG crew that participate in the forums are in a position to give an absolute answer, so contacting YYG is the best bet to get the exact details cleared up and not just have vague "maybe, maybe not" replies. :)
 

Juju

Member
Even YYG seems to have forgotten that clause.
They haven't.

can PIX be called a reverse engineering / decompiling tool?
No.

For sure.
Nope.

PIX doesn't give you any access to the game's source code. It's not decompiling because it doesn't spit out GML (or C++), and it's very hard to extract meaningful techniques purely by looking at PIX. You can tell how stuff is batched (and places where the devs can probably optimise the game!) but other than that, PIX is limited as a code reverse engineering tool. It's also hard to rip meaningful graphics from PIX, and though GMS asset dumpers do exist, they don't use PIX nor do they intercept the graphics pipeline.
 

Tthecreator

Your Creator!
" hurduur what about yyg emplyoees" "duurdhh I hope wii dey answer"
If only there was some magical symbol which could be used to send someone a notification when you write the name after it. The symbol could be a % or a $ or maybe even a @?

Okay sorry I'm just kidding, that's not very nice of me to say. No offense to anyone. Please consider whether anyone even want to take part in a conversation before tagging them. (or at least make a good summary and clear questions) (or just file a support ticket I guess)

I'm pretty sure this EULA thing is just to cover their asses. YYG would look the other way when it doesn't negatively impact them. Of course when making somethings 1.4 only I guess it does?
Also when directly asking yyg, no single employee would want to have any responsibility giving anyone the green light with some compiler hack.
There a multiple eula questionable project out there and yyg doesn't really seem to be go after them as of now.
So I'd say: asking for forgiveness is easier than asking for permission. (unless it's in court of course:p)
 
M

MishMash

Guest
I'm pretty sure this EULA thing is just to cover their asses. YYG would look the other way when it doesn't negatively impact them. Of course when making somethings 1.4 only I guess it does?
Also when directly asking yyg, no single employee would want to have any responsibility giving anyone the green light with some compiler hack.
There a multiple eula questionable project out there and yyg doesn't really seem to be go after them as of now.
So I'd say: asking for forgiveness is easier than asking for permission. (unless it's in court of course:p)
This is an interesting topic, as depending on how you look at it, it could go either way. On one hand, I do see that technology like this could create a false representation of GM in the eyes of potential consumers. For example, if I were to use it in my project and aspiring developers assumed it to be part of the core feature set, it could be a hindrance. However, on the flipside, this type of optimisation "can" be achieved in other ways, such as through the use of a bespoke DLL, an external application that communicates over the network etc; This schema just removes some of the awkward tasks and inconsistencies that those methods (that have been used before) provide.

Given the above case, especially the comment on DLLs being entirely legal, the achieved end-result would be the same, it is just the means through which that end-result is achieved. As it stands, i'm not in a position where this is essential, however it would definitely improve the playing experience of my project. When it comes to me genuinly considering using this trick in my commercial project, at that point i'll contact YYG directly. In my head, as Tthecreator said, I think it is a situation where they would look the other way, given that the intention is genuine, and it is not in an effort to undermine GM or exploit its power for personal game (such that it would if you were to make a derivative game-engine using GM's back-end).
 

Juju

Member
As far as I can see, you're not diving into the actual runner part of GM, you're adjusting the C++ that the compiler spits out. That stuff is your code, after all, and YYG can't stop you from changing your own code.

This is very exciting work, @MishMash, you should be proud. Had no idea you were English too! I run a meetup in London every month - would you be interested in popping down and giving a talk?
 
M

MishMash

Guest
As far as I can see, you're not diving into the actual runner part of GM, you're adjusting the C++ that the compiler spits out. That stuff is your code, after all, and YYG can't stop you from changing your own code.
This is very exciting work, @MishMash, you should be proud. Had no idea you were English too! I run a meetup in London every month - would you be interested in popping down and giving a talk?
I'm actually going to be moving to London in a few months (september/october time), and would be interested in coming along to that meetup anyway, sounds interesting :) Is it for general Indie developers, or GM specific O: ?

Whether a talk would actually be of interest is another topic, but I guess I could down the line. Haven't touched this much since initially posting, however i'll likely be implementing it into my project prior to release and by then should have more by way of practical results and a few established methods. If you hadn't seen it before, then you may also be interested in a similar method for replacing DLLs with native injected C++ code in YYC which can yield a good speed increase by removing all of the DLL call overhead. https://forum.yoyogames.com/index.php?threads/custom-c-code-in-yyc.4612/
 
Top