BABYLON.GUI AdvancedDynamicTexture optimization question/advice

I’m on my last leg of critical optimizations for game and getting close, but I’m running into a new ADT performance problem. For context: Been developing recently on new Macbook w AMD Radeon Pro 5500M 4GB (good card). Now I’m trying to optimize it on my iMac retina with a, semi meh AMD Radeon R9 M395 2048 MB, at retina sizes (0.5 hardware scaling level) – Everything I’ve tested on runs fine if I downscale to 1.0 hardware scaling, but I haven’t been able to get > 30 FPS on imac at 0.5 HWS since nearly when I started project. (Runs fine at 0.5 now on MBP)

I’ve known ADT was my problem for awhile, as it’s a card game and was using it for all the cards as well as the card in play’s attributes – But I just finished refactoring to using ALMOST no ADT, minus one part where it’s needed, and seeing a big performance hit still on imac at 0.5 (also should mention 3840x2116, not running it full screen).

Attaching screenshot below as much easier to visualize.

As mentioned in screenshot, previously there was up to > 100 ADT’s per match, (1 per card), at 1024x1024 each. Which even my new MBP would eventually run the GPU out of memory or something and slow down to 10-20 FPS, but no longer does that after refactor. - But imac still unable to render the ADT in a performant manner (10-20 FPS). If I skip building the description attributes or disable the player hands, it jumps back up to 50+.

The refactor I did (along with turning all the card (attributes/frame/number values into instanced sprite meshes using basis compression) was to Dynamically fill 4096x4096 ADT’s with GUI Grid controls, and then each card adds its own text to one of the textures when it’s created. So 1 512x512 texture per card, which allows me to limit to 2 4096x4096 ADT per match, for the most part (They will be dynamically allocated if I need more), then I pass the ADT to a custom shader which uses it like a sprite by setting instancedBuffers – But even with just the two 4096 textures (or 1), it tanks the performance down to 10-20. So I’m wondering if there is a setting I could be missing, or something I’m not understanding about what it’s doing (It’s not rendering new data to the canvas even if the texture hasn’t changed is it? I’m also using invalidRect optimization so I would think that if nothing is changing, performance should be stable.)

Things I’ve tried to no avail:

  1. noMipmaps = true,false (Which I’m still not sure if I want or don’t want mipmaps for this. The cards can go from small to big i.e. when being drawn or hovered, so I think maybe I do want mipmaps?)
  2. material.freeze() on the ADT materials
  3. useSmallestIdeal = true
  4. checkReadyOnEveryCall = false
  5. useBitmapCache = false,true

(Also, pointer events are turned off i.e. this.texture = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(this.mesh, this.width, this.height, false);

So I’m wondering if there is another setting that could free up performance, or something that could be causing the drastic frame drop that someone is aware of?

Any ideas would be much appreciated

Why using ADT texture to hold the cards?

I guess you don’t copy data in this texture very often, meaning it’s not several times per second but instead one time every X seconds or more?

Each time an ADT texture must be updated, the hidden canvas linked to the ADT must be copied to the texture, so for a 4096x4096 that’s quite a lot of data. And I think the texture then must be uploaded to the GPU, which takes additional time.

With a regular texture, you would incur no penalty as the texture would already sit on the GPU. Updating this texture may take more time (I don’t know how it would work, maybe you would have to recreate it), but if it’s done only when the player is playing / drawing a card, it may be acceptable.

ADT is a very versatile tech but it has its drawback as @Evgeni_Popov mentioned.

Maybe you could start by rendering it to a lower resolution (just the ADT and not the entire scene) with adt.renderScale = 0.5

The simple fact of manipulating a 4096x4096 texture will kill your GPU bandwidth. You must try to keep it in the 1024 ballpark

@Evgeni_Popov I am using the ADT to hold the descriptions only (the green circled part). It’s only updated if the card description changes, which is very rare, i.e. a player plays a card which gives a card an ability that needs to be shown in the description.

@Deltakosh Which is what is confusing me, as I am not updating the ADT in testing. Just the presence of the ADT in the scene, with any meshes enabled which are using it seems to cause the slowdown. As if the ADT is doing something every frame. In theory shouldn’t it be able to handle a 4096x4096 ADT texture that is not being changed often, or is the ADT doing something every X frames?

So it SHOULD not update on every frame but we need to make sure of that :slight_smile:
Can you repro somewhere?

Ya I will try to repro tomorrow. Tbh might be other factors contributing, not for sure, all I know is if I dispose both textures after scene loads everything is fine. However saw some weird behavior earlier where I stopped them from loading altogether and was seeing same drop. iMac +5k+gpu is the worst

1 Like

Hi @Deltakosh , we are debugging some performance issues ourselves and we are wondering about an ADT that we have in our scene that we define with res of 2048X2048.

var advancedTexture = GUI.AdvancedDynamicTexture.CreateForMesh(
plane,
2048,
2048
);

Are ADTs still set up to update every Frame? Do you expect that above ADT would perform well on mobile? Where we are really getting crushed right now is iOS in particular so every little bit counts. :slight_smile: