Expose canvas texture creation to ZScript

Post a reply

Smilies
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :geek: :ugeek: :!: :?: :idea: :arrow: :| :mrgreen: :3: :wub: >:( :blergh:
View more smilies

BBCode is ON
[img] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Expose canvas texture creation to ZScript

Re: Expose canvas texture creation to ZScript

by Boondorl » Sun Aug 17, 2025 9:51 pm

I think a hard limit is out of the question because it becomes impossible to know what a "safe" amount of textures is. One thing I haven't seen mentioned at all is the idea that multiple mods could be allocating textures for similar purposes. Assuming we have a tiny 1gb pool, this means mod A might think it's safe having only 600mb of textures mod B also thinks it's safe having only 700mb of textures. Combine these textures pools and now you suddenly have random errors showing up with seemingly no explanation as both mods work fine alone but break together. Fundamentally, this is a bad system that makes the idea of a safe range impossible, especially if someone decides to immediately allocate the entire space for their own mod (but I'm sure no one would do this out of bad faith, right? It's not like mods have been caught sabotaging each other in the past or anything).

I think one option here is to require a definition forward declaring how much memory you'll need so it can be tracked on the CPU side. Multiple mods combine their required amounts and give much better error tracing because we can actually detect these problems in advance and give proper warnings. This seems to be the single largest problem: it's too hard to actually track issues with this and debug if you're just allocating memory out of the blue. Mods can't really step on each other's toes here with an arena system because if a mod allocates less memory than it needs, it simply won't work standalone. Piggybacking can only work if it's an add-on intentionally aimed at an existing memory pool (still a bad idea, but again, easily debuggable for the modder). This fixes the huge problem which is just knowing the limit at all without making it trivial for mods to get in each other's way. If you wanted to introduce a hard limit on allocated space, the declaration is realistically where it'd be done so it could still be handled on a per-mod basis.

As for tracking textures, to be honest, I think this is being overthought. We don't need the GC to handle this imo, I think the simplest solution is to always wipe textures on level change, keeping them in memory otherwise. With the above arena we can capture runaway creation/unexpected sizes so needing to track this isn't necessary anymore, we already know exactly how much memory can exist for textures at a time. But wouldn't this be really awful to work with, having to constantly recreate them and all? Well, let's ask another question: are we planning on allowing these textures to be serialized? No other texture in the engine is, so I doubt these will be. Since they can't be serialized, they already have to be recreatable from scratch, otherwise loading a game will lose the texture. An example of this is Disdain. For our bloodied player model system, we track blood splats on Objects that can actually be serialized out and then draw on the texture whenever they're modified, creating a simple controller structure. Modders are already going to be forced down this route if they want to not break saves, so I don't see a harm in just clearing them on barriers that can already handle this. The only issue I could think of is if GZDoom is fundamentally not capable of doing this which feels like a problem outside of the scope of this feature if it's incapable of ever releasing resources on the GPU (and should maybe be said ahead of time instead of misleading people by telling them the problem is that bad ZScript coders exist).

Re: Expose canvas texture creation to ZScript

by kevansevans » Tue Aug 05, 2025 8:03 am

yeah, ngl, having to call a keep alive function every frame is a bit of a bad idea, and having it destroyed the instant it's not being rendered just adds way to much to the pile for the modder to juggle, because I don't think any of us want to put in visibility checks on a wall or sprite or whatever and call it every frame the canvas is found to be null. It's definitely a lot smarter to let the modder handle destroying them correctly, and the bigger issue there is how to properly communicate that need.

As I see it, these are the two big points that are unavoidable with creating canvases on the fly:

1) Modders are going to likely want a lot of arbitrary canvases, so it's going to need to be very flexible.
2) Modders also cannot have purely unlimited amounts of canvases due to the volatile nature of the Vulkan backend.

I think the proposed compromise of limiting it to 2GB of resources would meet both these points amicably, as one would really have to go out of their way to make 2048 256x256 textures.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 5:59 pm

phantombeta wrote: Mon Aug 04, 2025 5:09 pm shrug
Doesn't really matter if it's only if the keep alive function is called, or if it also keeps its contents as long as it's being rendered, the point was that it's not all that hard to come up with a system that allows the engine to automatically manage the lifetime of the hardware resources.
I never stated that it was an unsolvable problem. I explained why the original proposal to add a Canvas.Create function in the suggested form was a bad idea. Then you show you up with a completely different solution (force zscript code to confirm usage by calling a new canvas.KeepAlive() function every frame) where I ask you a few questions about the lifetime management of it and get shrugged. I'm done with this conversation.
Is that really a good reason to forbid it?
Yes, I think it is. The difference is the way GPU drivers crash an application - nobody thinks its the mods fault when the death message is "device lost", "could not allocate descriptor set" or "could not allocate texture bind index".
It's no different from how the Dispose pattern works in C# when you're handling hardware resources
C# is exactly the reason I don't like solutions leaning heavily on finalizer patterns. Where do you think all those horror stories I mentioned come from? Servers in trouble due to sockets not being disposed properly, files that can't be opened or created due to file handles still open, etc. The original .net framework is full of them. If you look closely at stuff they added later on they virtually always try to find a solution that does not require IDisposable and finalizers.

This will be my last post on this thread. I can't be bothered when its at the shrug level. Nothing more to be gained here. Shrug, I guess.

Re: Expose canvas texture creation to ZScript

by phantombeta » Mon Aug 04, 2025 5:09 pm

dpJudas wrote: Mon Aug 04, 2025 4:28 pm That will work but then why not always just drop the texture if keep alive isn't called?
shrug
Doesn't really matter if it's only if the keep alive function is called, or if it also keeps its contents as long as it's being rendered, the point was that it's not all that hard to come up with a system that allows the engine to automatically manage the lifetime of the hardware resources.
If that was the intent here why not just have a Canvas.SetSize(textureID, width, height) function?
That's what kevansevans suggested. I don't know AFADoomer's use case, but for a lot of use cases, just being able to resize a canvas texture is enough.
I don't trust that people won't generate dynamic canvas names if they have the possibility.
Is that really a good reason to forbid it? Modders can already leak memory in many ways, and GZDoom will just crash with an "out of memory" error with no indication that it's not the engine at fault. How is that any different from leaking GPU resources?
I really don't like the idea that GC will call the finalizer eventually because this isn't really a solution. I've heard way too many horror stories over the years from software where it runs horribly due to resource leaks of exactly this nature. There is nothing worse than software that behaves differently depending on when a garbage collector runs - sometimes it crashes because it didn't run in time, sometimes its fine.
It's not a solution, it's a safeguard in case the modder doesn't call Destroy themselves. You could even have it print a message to the console if it reaches the finalizer.
It's no different from how the Dispose pattern works in C# when you're handling hardware resources, except GZDoom's Destroy function makes the GC delete the object even if it has pointers to it. (it nulls the pointers, of course)
Either way, it doesn't really matter. Automatic management makes more sense here anyway.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 4:28 pm

phantombeta wrote: Mon Aug 04, 2025 3:53 pm I never said the contents would be kept. Like I said, you'd have a "keep alive" function on the ZScript side. If the modder doesn't call it every frame, it's their problem if the texture loses its contents.
That will work but then why not always just drop the texture if keep alive isn't called?
You can't change a canvas texture's size. If you want something that matches the screen's resolution (e.g., for postprocessing shaders), you can't do that currently.
If that was the intent here why not just have a Canvas.SetSize(textureID, width, height) function? I don't trust that people won't generate dynamic canvas names if they have the possibility.
Objects in ZScript already have a Destroy function, which is what I suggested. If the modder forgets to call it and just nulls the pointers to it, it still gets caught by the GC eventually.
I really don't like the idea that GC will call the finalizer eventually because this isn't really a solution. I've heard way too many horror stories over the years from software where it runs horribly due to resource leaks of exactly this nature. There is nothing worse than software that behaves differently depending on when a garbage collector runs - sometimes it crashes because it didn't run in time, sometimes its fine.

In any case, with the KeepAlive() function being a requirement to be called every frame I don't really care anymore as now I'll just kill any canvas that forgets to call the function. Lifetime tied to the call rather than the managed object.

Re: Expose canvas texture creation to ZScript

by phantombeta » Mon Aug 04, 2025 3:53 pm

dpJudas wrote: Mon Aug 04, 2025 3:07 pm If the engine destroys a texture due to not having seen it for a while there's no bringing it back. It could recreate it next time zscript/game uses it, but its contents will be lost. Effectively this will just be the 1024 limit anyway, except now you will notice by the textures turning black if haven't rendered/used them for a while.
I never said the contents would be kept. Like I said, you'd have a "keep alive" function on the ZScript side. If the modder doesn't call it every frame, it's their problem if the texture loses its contents.
If the canvas name is always the same you could just define it as a texture in ANIMDEFS already as it is today, what problem does it solve then?
You can't change a canvas texture's size. If you want something that matches the screen's resolution (e.g., for postprocessing shaders), you can't do that currently.
IMHO the proper way in a GC language is to have a Dispose/Destroy function that must be called. That's very easy for a modder to forget to do though.
Objects in ZScript already have a Destroy function, which is what I suggested. If the modder forgets to call it and just nulls the pointers to it, it still gets caught by the GC eventually.

Re: Expose canvas texture creation to ZScript

by kevansevans » Mon Aug 04, 2025 3:42 pm

dpJudas wrote: Mon Aug 04, 2025 3:07 pmIf the canvas name is always the same you could just define it as a texture in ANIMDEFS already as it is today, what problem does it solve then?
Personally, it's a massive pain in the ass having to juggle several lumps to get something "simple" done, and there has been several instances where I have wished we could just do it all in a single ZScript function. I have been begging in the discord that I'd love the ability to take the screenshot function and use that as a texture, however I've had to settle for defining a massive canvas texture that is bigger than anyone's monitor could possibly be so I can get 1:1 pixel placement and cover all possible monitor size cases. It'd be a lot better if I can just make it the exact size of the users screen, but here we are.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 3:07 pm

If the engine destroys a texture due to not having seen it for a while there's no bringing it back. It could recreate it next time zscript/game uses it, but its contents will be lost. Effectively this will just be the 1024 limit anyway, except now you will notice by the textures turning black if haven't rendered/used them for a while.

If the canvas name is always the same you could just define it as a texture in ANIMDEFS already as it is today, what problem does it solve then?

I brought up garbage collection because relying on the GC cleaning up anything but memory resources is generally a very bad idea. You never know when finalizers run (*) and as a result you could end up with a lot of extra textures no longer used but not collected yet. IMHO the proper way in a GC language is to have a Dispose/Destroy function that must be called. That's very easy for a modder to forget to do though.

*) In fact, one could argue finalizers was a terrible idea that was the wrong solution to resource management in GC languages.

Re: Expose canvas texture creation to ZScript

by phantombeta » Mon Aug 04, 2025 2:09 pm

I really don't get why this is such a concern. If it's tied to names like the OP suggested, it's not that easy to accidentally leak textures. You'd have to be deliberately using procedurally generated names to do that.

Garbage collection isn't a problem, making Destroy mark the texture for release makes sure it gets deleted when collected, and gives modders proper control over deleting it.

And it's not like the engine can't manage lifetime automatically, either. It wouldn't be all that hard to have it delete a texture if it hasn't been used in the last frame, and ZScript hasn't called some "keep alive" function on it. Then it'd call Destroy, ZScript would see it as null, and then either the modder handles that properly, or gets a VM abort.

Kevansevans' suggestion of having to define the texture name in ANIMDEFS as a "modifiable canvas texture" would also work pretty well for most use cases people might want this for, and that doesn't allow leaking textures.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 11:45 am

I meant the total GPU memory usage. 64 2048x2048 (16MB each) textures, 256 1024x1024 (4MB each), 1024 512x512 (1MB each), 1024 256x256 (256KB each; texture count limit kicks in instead).

Keep in mind that Nvidia and AMD still sell GPU's with 8 GB of memory. The frame buffers and other engine buffers consumes somewhere in the range 500 MB to 1 GB. On top of that you have to add game textures. Other applications may be loaded too which uses memory. That's why I suggested 1 GB as the upper limit, but sure, we can make it 2 GB too - my card doesn't care as it has more.

The 1024 texture count limit is due to hardware limits for bindless textures. You can safely assume that on PC you can have 65536 textures like that. Anything higher and there will be a lot of GPU's that can't do it. Once again this limit is shared between other things we want to place in bindless textures as well: game textures, lightmap textures, light probe environment map, etc. If we ever hit the 65K limit the engine is sort of fucked as now you have to completely redesign its bindless strategy as it can't assume it can just assign a slot for any texture. It doesn't have to be as low as 1024, but its dangerous if we allow unlimited textures.

Re: Expose canvas texture creation to ZScript

by kevansevans » Mon Aug 04, 2025 8:48 am

dpJudas wrote: Mon Aug 04, 2025 3:30 amnobody blames the mod - they blame the engine.
Haven't we universally agreed that people like this are idiots if they can't understand they're running a mod? I understand that it muddies the water when it comes to debugging the engine, but if someone comes into the community, kicking down doors, demanding the manager so they can complain that their version of GZ Mega Shit farded on their GPU and made it stinky, I think it's safe to dismiss them and write them off as unwilling to cooperate in finding out what the problem is. This isn't a unique problem to GZDoom.
dpJudas wrote: Mon Aug 04, 2025 3:37 am Just to clarify: the limit could be that you can allocate a maximum of 1024 textures and they can totally only use 1 gigabyte of memory. Exceed any of those and Canvas.Create will begin to return null or throw an exception.
Rachael wrote: Mon Aug 04, 2025 5:47 amI think it would be worth considering to put those limits inside user cvars. Because today those limits might seem generous, in 10 years they might seem a bit restrictive.
From what I can gather from researching how much memory textures can take up, a single 2048x2048 at 8bpp would take up around 4mb of system memory (both in ram and gpu, 5.3mb if mipmapped), meaning the hard limit there would be 256 textures. I want to agree with Rachael on this being a harsh restriction to a degree, but realistically people would have to go out of their way to reach this limit. Could a more fair compromise be to make it a 2gb limit? Or did you mean each texture would not be allowed to exceed in 1GB of needed resources?

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 6:20 am

I don't think its a good idea to let the user control stuff like this. Newer versions of GZDoom could increase the limit, but of course, those clinging to decade old graphics cards will then run into trouble. If you have it as a CVAR you just forward the nightmare to the mod: they will not know what kind of budget they have to work with and you'll get readme.txt files asking users to increase the limit. As someone that has to deal with the vulkan nightmare of limits varying between hardware, drivers and platforms, trust me, you do not want this. :)

Re: Expose canvas texture creation to ZScript

by Rachael » Mon Aug 04, 2025 5:47 am

I think it would be worth considering to put those limits inside user cvars. Because today those limits might seem generous, in 10 years they might seem a bit restrictive.

Also, if we're talking about limits, managing limits would be nice too, such as the ability to destroy canvas textures that are no longer needed and free the allocation.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 3:37 am

Just to clarify: the limit could be that you can allocate a maximum of 1024 textures and they can totally only use 1 gigabyte of memory. Exceed any of those and Canvas.Create will begin to return null or throw an exception.

Re: Expose canvas texture creation to ZScript

by dpJudas » Mon Aug 04, 2025 3:30 am

When the game dies with "device lost", "could not allocate descriptor set" or "could not allocate image" nobody blames the mod - they blame the engine.

The difference between Canvas.Create and what we have now is that today everyone (engine and mod) knows exactly how many textures they are going to have. With Canvas.Create a mod could slowly leak textures and eventually reach the limit Vulkan has internally and when that happens the game dies with an engine error. Only way to prevent it is for the engine to set its own internal limit to how many times it can be called and how much memory it can request. If we do that I personally have no objections to such a function.

Top