Expose canvas texture creation to ZScript

Remember, just because you request it, that doesn't mean you'll get it.

Moderator: GZDoom Developers

User avatar
kevansevans
Spotlight Team
Posts: 435
Joined: Tue Oct 05, 2010 12:04 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: Expose canvas texture creation to ZScript

Post by kevansevans »

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.
User avatar
phantombeta
Posts: 2175
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: Expose canvas texture creation to ZScript

Post by phantombeta »

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.
dpJudas
 
 
Posts: 3172
Joined: Sat May 28, 2016 1:01 pm

Re: Expose canvas texture creation to ZScript

Post by dpJudas »

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.
User avatar
phantombeta
Posts: 2175
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: Expose canvas texture creation to ZScript

Post by phantombeta »

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.
dpJudas
 
 
Posts: 3172
Joined: Sat May 28, 2016 1:01 pm

Re: Expose canvas texture creation to ZScript

Post by dpJudas »

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.
User avatar
kevansevans
Spotlight Team
Posts: 435
Joined: Tue Oct 05, 2010 12:04 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: Expose canvas texture creation to ZScript

Post by kevansevans »

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.
Boondorl
Posts: 169
Joined: Wed Jul 11, 2018 10:57 pm

Re: Expose canvas texture creation to ZScript

Post by Boondorl »

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).
Post Reply

Return to “Feature Suggestions [GZDoom]”