-
Notifications
You must be signed in to change notification settings - Fork 324
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
Allowing EnsoGL mouse to interact with more than 4096 sprites at the same time. #3351
Conversation
39c1e42
to
f1f8ba6
Compare
// === UnsetParentOnDrop === | ||
// ========================= | ||
|
||
/// Wrapper that unsets parent of a display object when dropped. |
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.
Maybe there should be a special note that this does not imply "taking ownership" of the Instance
(as they are clone_ref
able, and there is no guarantee, that there are no other instances that will be alive and usable after this is dropped.
I'm mentioning this, as this at first glance looks like a pattern where some Rust object is put in a wrapper that makes guarantees about the inner object, but it is not. It is purely a utility to call a method on the inner object once this UnsetParentOnDrop
sentinel is dropped.
/// Decode the [`PointerTarget`] from an RGBA value. If alpha is set to 0, the result will be | ||
/// background. In case alpha is 255, the result will be decoded based on the first 3 bytes, | ||
/// which allows for storing up to 16 581 375 unique IDs. | ||
fn decode_from_rgba(v: Vector4<u32>) -> Result<Self, DecodeError> { |
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.
Some additional description about how the encoding and decoding is done should be in this doc. Just to ensure it is clear in which order the R, G, and B values are used and that there is no trickery with the endianness.
} | ||
} | ||
} | ||
|
||
#[test] |
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.
The new encoding should still be tested.
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.
Comment from call: let's add docs to the decode line pointing to GLSL impl instead
let item_byte_size = T::item_gpu_byte_size() as i32; | ||
let item_type = T::item_gl_enum().into(); | ||
let rows = T::rows() as i32; | ||
let cols = T::cols() as i32; | ||
let col_byte_size = item_byte_size * rows; | ||
let stride = col_byte_size * cols; | ||
let normalize = false; |
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.
Why is this renamed? normalize
seems much more explicit.
lib/rust/web/src/lib.rs
Outdated
@@ -359,6 +359,14 @@ ops! { ReflectOps for Reflect | |||
/// [`get_nested`] to learn more. | |||
fn get_nested_object(target: &JsValue, keys: &[&str]) -> Result<Object, JsValue>; | |||
|
|||
/// Get the nested value of the provided object and cast it to [`Object`]. In case the |
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.
Should this be the same doc as below?
#[derive(Clone, CloneRef)] | ||
#[clone_ref(bound = "T:CloneRef")] | ||
pub struct EraseOnLastDrop<T: Erase> { | ||
elem: T, |
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.
Why does this need to store a second naked version of the element instead of just the Wrapped one?
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.
Performance reasons, however, this code was not longer used and it was removed.
GlobalInstanceId(u32); | ||
} | ||
|
||
shared2! { GlobalInstanceIdProvider |
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.
This data could be static
--because this is a truly global object (it would be wrong for more than one instance of it ever to exist), it feels weird to me that objects have fields identifying an instance of it.
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 is possible for multiple GlobalInstanceProvider
s to exist – every scene contains one. Right now, we have one scene everywhere, but our World
supports having multiple scenes. Each scene is connected to a separate WebGL canvas (and separate WebGL context), thus has separate symbol buffers and separate instance counters.
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 makes sense. The names or at least the docs could be more clear that these are actually scene-scoped, to ensure we avoid confusion when we have multiple scenes.
@@ -1188,6 +1188,32 @@ impl<Host> Object<Host> for Any<Host> { | |||
|
|||
|
|||
|
|||
// ========================= |
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.
This UnsetParentOnDrop
is cleaner than what it replaces, but the need for it it suggests a complex lifetime dynamic I don't fully understand.
Why is it that Sprite's display Instance needs to be unparented if the Sprite is dropped, but an Instance for any other object doesn't need this?
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.
This is an interesting question. You know, right now all things that you see on the screen are Sprites, so this works for everything we have. We could theoretically use this pattern in every object (like a node, that contains a lot of sprites), but I'm not yet sure what benefits it would give us. But this is an interesting potential change (definitely not part of this PR as it could be really big). CC @farmaazon, what do you think?
[ci no chfangelog needed]
Pull Request Description
This PR implements Enso mouse system should allow working with more than 4096 objects.. Until now, all sprites were distinguished by two values,
symbol_id
andinstance_id
. These values were encoded in an off-screen texture, on 12 bits each. This PR introduces a new abstraction,GlobalInstanceId
, which unifiessymbol_id
andinstance_id
for the purpose of mouse target discovery. Bothsymbol_id
andinstance_id
still exist, because they are usable in other parts of the codebase. Moreover, this PR introduces a few improvements:NoCloneBecauseOfCustomDrop
, which prevents the structure from implementingClone
and checks if the structure implements customDrop
behavior.Sprite
implementation to a new conceptSymbolInstance
.shared2
macro, which is similar toshared
, but unlikeshared
it is understandable by IntelliJ. However,shared2
does not support all constructs yet.#[entry_point]
macro, which simplifies entry point definition.FIXMES
Please note that one FIXME is left in the lib/rust/ensogl/core/src/debug/stats.rs file and should be investigated in the future. The cause is not introduced by this PR and because it requires some additional investigation time, it's not covered here.
Testing
Checklist
Please include the following checklist in your PR:
./run dist
and./run watch
.