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

deprecate changing buffer size with setArray() #17418

Closed
wants to merge 1 commit into from

Conversation

aardgoose
Copy link
Contributor

Relating to #14730 issues with BufferAttribute.dynamic flag overloading.

Deprecate changing a BufferAttribute's size with .setArray() as a prelude to removing this ability.

Now all internal renderer and GPU state relating to BufferAttributes is weakly referenced with the use of a WeakMap, an attrribute can simply be resized by overwriting with a new BufferAttribute with Geometry.addAttribute() without long term memory leaks, this has little additional overhead over using setArray() to resize an attribute. #17063 would allow users explict control over heap usage if waiting for GC , but is not a strict requirement.

After one or more releases this warning can be replaced with an exception, and WebGLBufferATtribute simplified to restore the dynamic flag to it's original purpose.

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 5, 2019

I think BufferAttribute.setArray() should go to three.legacy.js. But only if #17063 goes in from my point of view. The deprecation of this method also means to remove its usage in GLTFLoader and BufferGeometryUtils.mergeVertices().

As mentioned here #17242 (comment), we should encourage developers to call dispose() when resources become obsolete.

and WebGLBufferATtribute simplified to restore the dynamic flag to it's original purpose.

Like mentioned here #14730 (comment), I vote to remove BufferAttribute.dynamic and introduce BufferAttribute.usage instead. This will map much more nicely to the underlying WebGL API.

@aardgoose
Copy link
Contributor Author

I'm not sure if anyone uses it in this way, but using setArray() to replace a buffer's data with an new equal sized buffer gives the user a method to use the purportedly superior BufferSubData() rather than BufferData() which using a new BufferAttribute() requires.

It could be argued that this is a reason to support setArray(), say for getting new ArrayBuffers from a worker.

Anyway, just deprecating resizing is the minimum change required to sort out the dynamic flag.

Regarding .dispose() I completely agree it should be the preferred method and should be added, but with WeakMap() in use it isn't essential.

Regarding the naming of .dynamic I haven't got an opinion either way,

@mrdoob
Copy link
Owner

mrdoob commented Sep 6, 2019

I agree with @Mugen87, I think we should just deprecate setArray().

@mrdoob
Copy link
Owner

mrdoob commented Sep 6, 2019

The only thing that annoys me is suggesting using addAttribute() instead.

<rant>
The method doesn't really add, it just sets...

A method named setAttribute() sounds better. Which would make addAttribute redundant.

We could then follow WeakMap naming and rename removeAttribute() to deleteAttribute() and end up with getAttribute(), setAttribute() and deleteAttribute().
</rant>

@aardgoose
Copy link
Contributor Author

OK, no problem with that. I don't use setArray() myself, but playing devil's advocate to some extent for anyone that does, after the pain with it previously.

Do you want a PR to deprecate it or does @Mugen87 have it in progress?

Regards having setAttribute, if serious, you would want to do that before removing render support for Geometry() I assume.

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 6, 2019

First step: #17439

@donmccurdy
Copy link
Collaborator

... using setArray() to replace a buffer's data with an new equal sized buffer gives the user a method to use the purportedly superior BufferSubData() rather than BufferData()

Would copyArray, copyAt, and set( array, offset ) use BufferSubData? They seem like more obvious APIs for that purpose, and I'm OK with removing setArray() if so.

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 6, 2019

@aardgoose Would you like to do a PR which deprecates BufferAttribute.setArray() and InterleavedBuffer.setArray() (I mean moving to three.legacy.js)? After #17439, there should be no dependencies in core and examples to both methods anymore.

In this change, it would be also necessary to update the docs and unit tests.

@EliasHasle
Copy link
Contributor

We could then follow WeakMap naming and rename removeAttribute() to deleteAttribute() and end up with getAttribute(), setAttribute() and deleteAttribute().

It is more accurate, but... as a user, I imagine users will actually want to do like this instead:

geometry.attributes.position = new THREE.BufferAttribute(posArray, 3); //set
const pos = geometry.attributes.position; //get
delete geometry.attributes.position; //delete

To my best understanding, this would require geometry.attributes to be a Proxy. All the additional code execution, including differences between assigning and reassigning (automatic dispose on old value), will be abstracted away, so the user is only dealing with what matters to him/her. This may not be the most backward-compatible solution, though. Nor the most "honest" one, in that (potentially) advanced logic is concealed as simple property assignment.

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 9, 2019

To my best understanding, this would require geometry.attributes to be a Proxy.

@EliasHasle Can you please clarify what you are talking about? The implementation of BufferGeometry.setAttribute() and BufferGeometry.deleteAttribute() would not be different from the current methods.

@EliasHasle
Copy link
Contributor

@Mugen87 I am just mentioning the possibility for introducing an alternative API, since @mrdoob proposed a breaking change (albeit only a renaming).

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 9, 2019

Renaming the methods would not be a breaking change since you can keep the "old" methods in three.legacy.js and delegate any invocation to the new API (and log a respective deprecation warning).

@EliasHasle
Copy link
Contributor

OK. That would be possible with my suggestion too. Anyway, I mentioned it because there was talk of a possible API change for this (whether breaking or not).

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 9, 2019

That would be possible with my suggestion too.

Well, you would need a polyfill for IE11 since it does not support the Proxy object.

https://caniuse.com/#search=proxy

@EliasHasle
Copy link
Contributor

EliasHasle commented Sep 9, 2019

I don't think Proxies can be (fully) polyfilled at all. In particular, I see no way except proxies to trap arbitrary keys (attribute names in my example).

Off-topic about IE11 supportAnyway, why support IE11, which is used by less than 2%, has not seen a release since 2013 and is abandoned in favor of Edge by Microsoft. Not to mention it is a horrible browser, and I can never imagine that those interested in three.js or other WebGL applications ever use it.

@Mugen87
Copy link
Collaborator

Mugen87 commented Sep 9, 2019

This thread is not the right place to discuss IE11 support. It's just the status quo and the development needs to respect the current supported browsers.

Related: https://github.com/GoogleChrome/proxy-polyfill

@aardgoose
Copy link
Contributor Author

PR to deprecate setArray #17454

@aardgoose
Copy link
Contributor Author

replaced with #17454

@aardgoose aardgoose closed this Sep 9, 2019
@aardgoose aardgoose deleted the dep-resize branch September 9, 2019 19:40
lojjic added a commit to protectwise/troika that referenced this pull request Jul 19, 2020
Fixes #69. This works around an issue introduced in Three r117 where a
given geometry uses the size of any InstancedBufferAttribute as a max
for `instanceCount`, and caches that for the lifetime of the geometry
even if the attribute is replaced with one of a different size.

It's unclear if this is a ThreeJS bug or a if our approach of "resizing"
by replacing the attribute is truly unsupported; the discussion in
mrdoob/three.js#19706 is ambiguous,
mrdoob/three.js#19595 implies it's not
allowed, and mrdoob/three.js#17418 implies it
should be allowed.
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.

5 participants