Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add New GPU Texture Backend for advanced Usages (see paint example !) #855

Closed
wants to merge 28 commits into from

Conversation

cjbrigato
Copy link
Contributor

@cjbrigato cjbrigato commented Sep 24, 2024

Work in progress, do not merge.
Fixe many image related things ( complexe use of state, widgets bloat, GPU Resources Leaks, etc)

loadimageAdvanced example

loadimage.webm

new AsyncImage example

asyncimagesend.webm

new "paint" basic example

paintexample.webm

@gucio321
Copy link
Collaborator

@cjbrigato how is it going?

@cjbrigato
Copy link
Contributor Author

I have to rebase on master then to pass the whole linter.
If you can wait ~12h it'll be done, but it will still lack a bit of documentation and the "OnFailure" Layout that was part of the old ImageWithURL widget

@gucio321
Copy link
Collaborator

no problem, we can wait 😄

@cjbrigato
Copy link
Contributor Author

@gucio321 oh come on

go 1.22

toolchain go1.23.1

you are mean with me XD. I really wasn't ready for 1.23 toolchain. Anyway, I'm diving in !

@gucio321
Copy link
Collaborator

@cjbrigato just a protip: you could just git merge upstream/master then you need to solve conflicts only once ;-)

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 26, 2024

@gucio321 the PR is ready.
Added new example "asyncimage", demonstrating the ease of use of "Stateful" version of the ReflectiveBoundTexture, alongside with "pure imgui" windows with noOS Decoration. Also demonstrate the "file:///" loading scheme and "SurfaceLoaders" usage.
This should all be really easy to extend, in GIU or at end user level.
This do not use the whole and complicated widget state system in context.
Hope you don't dislike too much this PR, I know it is strongly opinionated at some point, but it feel quite robust, and puts the GPU Bound resources bugs far away.

Thanks in advance !

And keep up the amazing work !
Full Documentation and explanation are to come in next PR.

@cjbrigato cjbrigato marked this pull request as ready for review September 26, 2024 03:54
cleaning

Add ImageV/ImageButton casting from structure, remove pprof in loadimages

_

add

setsurfacesn

forceCOmmit

We are nearly done there. Fix Onclick widget with Size consideration, Add Scale operation in imageWidget, implement SurfaceLoaders for easy extension of loading images, change loading image example for advanced drawings and controls, updates URL downloaded images. Last Step: URL With OnError/OnLoading to mimic old behavior with better extension. Linting, Documentation.
* permits statefull state and async operation (goroutines)
* keep state in mainloop, or be reset if needed
* load is async and takes SurfaceLoader interface
* onReset, onLoading, onFailure, onSuccess callbacks
* Kept simple as ever, can go to an ImageWidget
* or can be used cleverly in a customWidget

Incoming loadimage exemple
Featuring the whole StatefullReflectiveBoundTexture.
This quite lacks documentation but I'll do that in next PR.
@cjbrigato cjbrigato force-pushed the Fix-ImageWithRGBAWidget branch from 4084279 to b791da3 Compare September 26, 2024 04:11
@cjbrigato
Copy link
Contributor Author

(properly rebased so review is possible)

@gucio321 gucio321 self-requested a review September 26, 2024 06:52
Copy link
Collaborator

@gucio321 gucio321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks cool, but i have some more points:

  • could you just replace the old imagewithrgba with your new implementation (or implemen it there somehow), I think the current version of an image is still broke but could be easily fixed now
  • i'd opt for adding a missing doc comments already here (tbh i have no ideas why golqngci passes without them)

Just don't feel like you are under pressure to finish this asap. It's an oss project and we work here when we want t and have time 😁

ReflectiveBoundTexture.go Outdated Show resolved Hide resolved
ReflectiveBoundTexture.go Outdated Show resolved Hide resolved
@cjbrigato
Copy link
Contributor Author

It looks cool, but i have some more points:

  • could you just replace the old imagewithrgba with your new implementation (or implemen it there somehow), I think the current version of an image is still broke but could be easily fixed now
  • i'd opt for adding a missing doc comments already here (tbh i have no ideas why golqngci passes without them)

Just don't feel like you are under pressure to finish this asap. It's an oss project and we work here when we want t and have time 😁

Actually i'm using it in an important project, so the pressure does not come from giu but from the project context ;)

made the two little changed you asked for, will update documentation and will make the StatefullReflective underlying object of ImageWithRGBA/ImageWithURL :)

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 26, 2024

@gucio321 problem with "ImageWithRGBA" is the way itself it's designed: Even with my solution, which ensure unbindings, you have to "keep" the object somewhere as to manage it's state and to ensure unbinding. You cannot count on finalizer at all there.
Problem is that ImageWithRGBA and subsequent binds textures then "forget" about GPU Resources. Using my new object result in the same behavior if we don't either Unbind or keep track of an instanciated object.

I deeply advice against the current design of the ImageWith* object right now, an encourage users to keep track of objects that BIND resources to GPU, which is the case for textures.

We can "hide" such object management on GIU side, and it will work... but for the very case of Texture I still think this is a very bad choice, hence the provided "loadimage" example changes.

I'll provide a change to "ImageWithRGBA" which demonstrate "hidden management" of the GPU Resources binding but again I strongly advice not to use it as is.
The design is very well thought for other objects indeed (labels,buttons, etc) but these are not GPU Bound object like resources, so this is absolutely not comparable.

see: #855 (comment)

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 26, 2024

@gucio321 I have a proposal being inbetween, the old "ImageWithX" and the user fully managed state.

I pushed some Methods to ReflectiveBoundTexture that result in only needing keeping the ReflectiveBoundTexture on user side before usage, then is simple as the old Widget usage:

This would work and be best of both world.
I've already prepared so it works with "ImageWithRGBA", "WithFile" and "WithURL" methods, all returning an ImageWidget already

See: d1485b1

PS: users already have to managed their own owbject when using InputTXT, DragInt etc so I see no reason why they would not do the same with Textures.

Edit: By Just writing the previous line I think I know exactly what is the proper design to propose :) Hold on

See: #855 (comment)

They are now compatible with legacy loadimage, which is also back !
now provide loadimageAdvanced and asyncimage example for complex
examples

The only new need of legacy ImageWidget usage is that you provide
a pointer to ReflectiveBoundTexture for WithRGBA/File
a pointer to StatefulReflectiveBoundTexture for WithURL due
to its async nature and the custom layout perStates.

This should not be hard to manage it's the very same as providing
pointer to string for InputText, or pointer to any objet for
other widgets !
@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 26, 2024

** I got it !**

@gucio321
loadimage become loadimageadvanced example
asyncimage is also there
but the pre-PR loadimage example is BACK with no modification in design except that the user should provide a pointer to the backend object in the very same way a user should provide a pointer to string, bool, int, float whatever for other RW widgets !

See: https://github.com/AllenDang/giu/pull/855/files#diff-549290e4ff1313d18f9138dbb7fa403cea00f702d0e681ed50219cbb643431a2

I think this is quite the right track :)

Note the legacy loadimage example takes max of 22MB footprint in GPUResources now :D

Now, back to linting, documentation AND I spoted a little forgotten object: the ImageButton widget.

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 27, 2024

@gucio321
yes i'll use embed, provide the missing save/open undo and brush sizing func too. I specifically took < 64px icons with embed in mind
After I made the changes you asked for.
Glad you like it, I literally made it to kill time while waiting for review

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 27, 2024

@gucio321 do you have any "quick" implementation on puting the &ReflectiveBoundTexture{} into your giu.Context state machinery ? It's being quite a PR and when I started looking at
GetState[T any, PT genericDisposable[T]](c *context, id string) PT {, even If I love Generics, if I can avoid diving in too much I'd be glad.
Also I've never seen doubling a SyncMap usage with mutexes, since the whole point of the syncMap is to avoir having to handle mutexes.

@gucio321
Copy link
Collaborator

gucio321 commented Sep 27, 2024

@gucio321 do you have any "quick" implementation on puting the &ReflectiveBoundTexture{} into your giu.Context state machinery ?

yeah, there was one already but it wasn't perfect I think.
Let me search a sec...

e.g. here: https://github.com/gucio321/yamler/blob/master/pkg/widget/state.go

type State struct {
   // anything you want here
}

func (s *State) Dispose() {
	// noting to do here
}

func (w *Widget) GetState() *State {
	if s := giu.GetState[State](giu.Context, w.stateID()); s != nil {
		return s
	}

	newState := w.newState()
	giu.SetState(giu.Context, w.stateID(), newState)

	return w.GetState()
}

func (w *Widget) newState() *State {
	return &State{
                // initialize here
        }
}

Edit And you need stateID (in case of image it should be (*ImageWidget).id or something like that

@gucio321
Copy link
Collaborator

@cjbrigato just wanted to warn you: I suppose something is broken inside giu and State is disposed every frame (?)
I'm investigating right now

@cjbrigato
Copy link
Contributor Author

That would explain part of initial imagewithrgba bug. Yes the finalizer was an issue but there definitely was something more going on

@gucio321
Copy link
Collaborator

That would explain part of initial imagewithrgba bug. Yes the finalizer was an issue but there definitely was something more going on

Yes and yes ;-)

I think that also that sync should be investigated some day.

btw, I've added this state example to FAQ 😸
https://github.com/AllenDang/giu/wiki/FAQ#state

@cjbrigato
Copy link
Contributor Author

Good catch.
When do you merge it so I can rebase ?

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 28, 2024

I won't have time to work on this this weekend and it still lack the state for the widget and for some reason I'm struggling with having a dedicated surfaceLoader working with embed.FS (for paint) but I'll get back to it on monday

@gucio321
Copy link
Collaborator

@cjbrigato I see you updating paint example ;-)

Glad you like it, I literally made it to kill time while waiting for review

Does it mean I should review?

@cjbrigato
Copy link
Contributor Author

cjbrigato commented Sep 30, 2024

@gucio321 I just could not resist providing brush size and undo buffer to the paint example so it's done. I'll get back to the state machinery tommorow but in the meantime* do we have an ETA on linting example directories ?

I don't think you should review before I do the requested changes on state and ViewportConfig too

@gucio321
Copy link
Collaborator

do we have an ETA on linting example directories ?

I have an answer from golangci how to enable it but it'd rquire me to fix a ton of isues on current code 😄

BTW Do you want me to merge #866 now or wait for this (it may be a small breaking change but i can fix it on my PR later)?

@cjbrigato
Copy link
Contributor Author

do we have an ETA on linting example directories ?

I have an answer from golangci how to enable it but it'd rquire me to fix a ton of isues on current code 😄

BTW Do you want me to merge #866 now or wait for this (it may be a small breaking change but i can fix it on my PR later)?

Yes please merge, i'll rebase and fix quickly tommorow then handle the state !

@gucio321
Copy link
Collaborator

gucio321 commented Oct 1, 2024

@cjbrigato now linting examples works.
I'm going to reenable revive linter to enforce correct documentation but idk when I'll be able to do that as giu still misses some docs.

BTW, sorry for change in ImageWidget.go

@cjbrigato
Copy link
Contributor Author

@gucio321 I tought your changes on state would fix original but same problem as ever, GPU filling memory in under 3minutes.

image

So.. i'll rebase and retry my luck on imagewidget but putting the reflectiveTexture in state

@cjbrigato cjbrigato changed the title Fix image with rgba widget Add New GPU Texture Backend for advanced Usages (see paint example !) Oct 3, 2024
@cjbrigato
Copy link
Contributor Author

@gucio321 fixed ImageWithRGBA in #869

This PR now is renamed and serve other purpose ("advance" usage for power users ;) )

@cjbrigato
Copy link
Contributor Author

I'm closing this in favor of new pr, because of the changes in master

@cjbrigato cjbrigato closed this Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants