-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Fix image subRegion... again... #13072 #13075
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
Open
Beilinson
wants to merge
1
commit into
CesiumGS:main
Choose a base branch
from
Beilinson:fix-billboard-subregion-v2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+6
−3
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Help me understand how this solves the issue? The issue occurs when returning a resolved promise, and you're saying that
awaiting that causes a one-frame delay (even though it's already resolved, microtask queue shenanigans?) that causes this bug?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just kinda annoying - I don't like relying on
instanceof. It generally indicates something has been designed incorrectly (which is already definitely the case in terms of overall billboard code architecture / texture loading, but I was hoping we improved on that last time).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's exactly right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do
typeofinstead like I did withaddImageSubRegionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But i definitely agree with you regarding the billboard texture architecture. IMO the best option long term is to do what I suggested in #12958 (comment), but as I mentioned there this will also fail for CallbackProperties so we still need some way of synchronously accessing already resolved textures + subregions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the bright side, this isn't much of a hot code path. It's not something that really runs every frame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to sleep on this. I’ve been reading up on the "Releasing Zalgo" anti-pattern, which warns against APIs that return either a sync value or a promise depending something.
Since the recommendation is to be consistent (always sync or always async), and considering this function is called every frame for the entity api, returning a Promise here might just be the root cause.
Idea:
then basically all the areas of the code that currently run after
awaitwill just be refactored to run given the value has returned, otherwise retrigger a subsequent check onframeState.afterRenderor something along those lines. Thoughts?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No really constructive comments (except for reiterating how much I appreciate the thoroughness and thoughtfulness that you're putting into that).
But I cannot pass the chance to chime in when there's a JavaScript/async rant 🙂 What bugs me:
asyncis viral. You can design a beautiful, clean, efficient, slim, versatile API. And at some point, 20 steps down the call chain, you suddenly have to call someasyncfunction, and thisasyncwill bubble up, until themainfunction, so to speak, and pollute your whole API with a breaking change. (And when Zalgo is already mentioned, the step to this meme is not so large...)For me, the ugly consequence is: When you define an interface, you have to declare all functions as
async, period. Not doing so will result in a breaking change sooner or later.(And the following is not as sarcastic as it may look at the first glance: I once considered to ""design"" a new language, called 'AsyncScript', which is just JavaScript with each function declaration being
asyncby default, and each function call beingawaited by default. Let the compiler and runtime sort out optimizations here - this is a syntactical level that a software engineer should not be concerned with).All this is somewhat unrelated to fixing an existing bug, or handle an existing shortcoming or inconsistency in a large codebase. The combination of "promises/callbacks" and the state management (something being "LOADED" or "READY" or whatnot) requires great care and thorough documentation. I hope that PRs like this lead to a gradual improvement here.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to say, a (large) part of me agrees viscerally with this sentiment ("
asyncis viral"). But there's a smaller part of me that always thinks "I must just not know the proper design principles for async programming." I feel that I have a good grasp on clean code design in general, but this must require an entirely separate regime of thought.Could be wrong, that's just the nagging feeling I get! I will say, when I last did some async stuff in the
Materialclass, my strategy was - rather than lettingasyncbubble up and pollute the whole stack - to simply notawaitthe promise once it got to a level where it didn't matter whether it was synchronous or not. Then, that function (and its ancestors) do not have to be marked async.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That may be applicable in some cases. Particularly in CesiumJS, where many structures are revolving around the assumption that the application is running indefinitely, and ~"some
update" is called every frame, and the promise just sets someready-flag so that thisupdatefunction can do someif (ready) render(); else dont();.I recently had/currently have to deal with that. A "(web) request" involves a promise, basically for ~"the tile content". This promise is never
awaited. When it's done, it's done. And then, it just changes some state somewhere, so that something else happens in the nextupdate.But this has two drawbacks:
awaited, eventually. Things likepollToPromiseare just crutches for converting an un-awaited promise (that is hidden deeply in opaque structures, and that does some state change) back into an awaitable promise - namely, by polling for the desired state change.I occasionally advocated for enabling something like https://typescript-eslint.io/rules/no-floating-promises/ - I'm pretty sure that there are some dangling promises in CesiumJS that could turn out the reasons for bugs. Even if it's sometimes intended, I think that making that explicit (and rasing awareness) by having to insert some ESLint-'ignore' could make sense.
And after all, I'm in the camp of "There are no asynchronous operations,". Whether or not something should be executed asynchronously has to be decided by the caller. Yes, you'd usually not block/wait for some web request. But that should rather be handled with something like
promise = makeAsync(thatWebRequest());than the other way around.