ebiten icon indicating copy to clipboard operation
ebiten copied to clipboard

[ebitenginedebug] Provide the ID of an *ebiten.Image somehow

Open divVerent opened this issue 1 year ago • 21 comments

If ebitenginedebug build tag is set, it prints out the list of textures and how they are used in the various render passes. This is nice, however it would be even nicer if I could refer to their texture IDs in debug log messages.

Currently I am using this nasty private field hackery here: https://github.com/divVerent/aaaaxy/blob/main/internal/offscreen/alloc.go#L41

But clearly this isn't nice at all. So I'd like to kindly request an explicit API to get this info (ideally not just the id but also the rectangle on a texture that an image occupies).

One idea could be adding a String() method to *ebiten.Image that returns this info, but of course this could be made dependent on the ebitenginedebug build tag. A lot of plumbing is involved to get this though... due to all those layers :)

A totally different approach BTW could be going the other way round - if ebiten.Image had a SetDebugName() method by which I can give a texture a name, ebitenginedebug could show those names instead of or additionally to the IDs, which would solve the same problem.

divVerent avatar Jul 15 '22 14:07 divVerent

The relationship between one *ebiten.Image and one texture is N:1, so the thing is not so simple.

You can dump an image by the EBITENGINE_INTERNAL_IMAGES_KEY environment variable btw.

hajimehoshi avatar Jul 15 '22 14:07 hajimehoshi

Yeah, I know they can be dumped; but for debugging it'd just be even nicer to just have names in the debug output.

As for n:1, one idea could be listing with each texture ID just the set of all names the texture ID has attached to.

divVerent avatar Jul 15 '22 14:07 divVerent

Sure. So my understanding is what we want is to know which internal texture is used for an *ebiten.Image. Let me think...

hajimehoshi avatar Jul 15 '22 14:07 hajimehoshi

Yeah. Ideal from a curious developer's POV would be a String() method that returns something like "texture 17 origin 100,200 size 300x400"; the diametral opposite alternative of just allowing to attach names to textures that are removed when the image with the name is disposed, and displaying these names in ebitenginedebug output, would however work fine too, and would not create danger of developers relying on the exact String() output.

divVerent avatar Jul 15 '22 14:07 divVerent

Yeah, func (*ebiten.Image) DebugInfo() string for examle sounds a nice idea.

hajimehoshi avatar Jul 15 '22 17:07 hajimehoshi

I started working on this issue, but I want to discuss it first before making a pull request

Proposal: make it return a struct instead of a string, kinda like

type ImageDebugInfo struct {
    ID int
    OriginX int
    OriginY int
    Width   int
    Height  int
}

And let's discuss what other fields can be included here? Original texture size? atlas.ImageType? mipmap.Mipmap.Volatile? Maybe even something like Mipmap's highest level?

RusAD32 avatar Jul 29 '22 10:07 RusAD32

Exposing internal information is a very risky issue and that's why I thought I would start with a string. I don't think I can determine this immediately and that's why I set the milestone as v2.5.0...

hajimehoshi avatar Jul 29 '22 11:07 hajimehoshi

Thank you for tackling this issue, by the way!

hajimehoshi avatar Jul 29 '22 11:07 hajimehoshi

No problem! When you come to some conclusion, can you please tag me so that I don't miss it?

RusAD32 avatar Jul 29 '22 11:07 RusAD32

Sure!

hajimehoshi avatar Jul 29 '22 11:07 hajimehoshi

@divVerent In the first place, I was wondering why you want texture internal IDs. It doesn't sound right to have something relying on internal texture IDs (even though this is for debugging)

hajimehoshi avatar Feb 10 '23 16:02 hajimehoshi

What I really want to achieve is correlate the ebitendebug info with the textures the game actually uses. To do that, I print out the texture IDs so I can, as a human, know which texture my game uses ended up on which system texture, which in turn lets me deal with apitrace data much easier.

However, this isn't the only approach that would fulfill this. What if you instead added this to the API:

func (*i Image) SetDebugName(name string)

which is a NOP unless the build tag ebitendebug is enabled. If it is, the debug report that is printed every frame will list every texture with the set of all names that have been attached to it (which means that SetDebugName on any texture has to propagate down to the atlas, and freeing the texture in turn also has to detach the name from the atlas again).

divVerent avatar Feb 10 '23 18:02 divVerent

To be clear, even cooler would be if Ebitengine even could then track which region has which name, so the EBITENGINE_INTERNAL_IMAGES_KEY dump would then also include a text file that contain the mapping from each name to the texture number and the exact region on it.

But a mere name list would already be sufficient - anything beyond would be nicer of course but seldomly actually needed.

divVerent avatar Feb 10 '23 18:02 divVerent

It sounds OK-ish to add an API that works only with ebitenginedebug.

which in turn lets me deal with apitrace data much easier.

I was wondering what kind of data tracing you are doing.

hajimehoshi avatar Feb 14 '23 09:02 hajimehoshi

Mainly trying to use these tools to improve performance - one factor of which may be changing which offscreen texture is used for what purpose to e.g. reduce GL state changes. Although it'd also have helped figure out the recent OpenGL active texture bug much faster, as I could have the confidently said that a given render call was using the wrong texture.

If adding an API that only works with ebitenginedebug, it'd still be nice to have its calls compile when the tag isn't set (but then the function should do nothing at all).

A very simple impl of such API could BTW be just printing to stderr the name and the texture ID - maybe simpler than actually remembering. But actually storing the name and using it for ebitenginedebug output would be best.

divVerent avatar Feb 14 '23 13:02 divVerent

If adding an API that only works with ebitenginedebug, it'd still be nice to have its calls compile when the tag isn't set (but then the function should do nothing at all).

Yeah I think that makes sense.

A very simple impl of such API could BTW be just printing to stderr the name and the texture ID - maybe simpler than actually remembering. But actually storing the name and using it for ebitenginedebug output would be best.

An image is just a part of a texture. What if multple calls for the same texture happen? Would the last call work?

hajimehoshi avatar Feb 14 '23 17:02 hajimehoshi

It would really be much more useful to keep all names of images on the given texture.

However it would sure be OK to require the names to be unique, so just tracking map[string]struct{} as a string set on a texture would suffice.

divVerent avatar Feb 14 '23 17:02 divVerent

I'm afraid I need more investigation, so let me postpone this to v2.6.

hajimehoshi avatar Feb 27 '23 04:02 hajimehoshi

Sure, sounds good; for now I do have a workaround by cowboy accessing private fields, so this can wait till we have a nice solution.

Am So., 26. Feb. 2023 um 20:24 Uhr schrieb Hajime Hoshi < @.***>:

I'm afraid I need more investigation, so let me postpone this to v2.6.

— Reply to this email directly, view it on GitHub https://github.com/hajimehoshi/ebiten/issues/2207#issuecomment-1445687107, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB5NMH3YYW2GK2TY6QPEHDWZQT6RANCNFSM53VXAABQ . You are receiving this because you were mentioned.Message ID: @.***>

divVerent avatar Feb 27 '23 15:02 divVerent

This seems more difficult than I expected. Ebitengine now has 1:n relationships between images and textures, but the internal details might be changed later.

SetDebugName sounded a good idea but this would not work when another intermediate thing is introduced between an image and an texture. Another thing is how to manage image lifetimes: when Ebitengine internal tries to dump texture info with the debug-named images, Ebitengine internal should hold references to such images. It would be hard to release them appropriately.

hajimehoshi avatar Aug 12 '23 18:08 hajimehoshi

https://pkg.go.dev/runtime/metrics seems interesting.

hajimehoshi avatar Sep 13 '23 16:09 hajimehoshi