-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
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
depthTexture share source after RenderTarget.clone() #30540
Comments
Also, shouldn't every texture in WebGLRenderTarget.textures receive a new Source? |
@Mugen87 can we revert #30570 and please give more than an hour between making a PR and merging it to give time for feedback and discussion in the future? What might be considered "correct" API behavior here is not obvious. In the same way that two Meshes can share a material and geometry after clone (see #30340), conceptually there is no reason that two render targets or frame buffers should not be able to share and render to the same underlying textures. Users can assign and clone textures as-needed depending on their use case. I'd argue the only reason I'm curious what the conceptual line is here? Why should Mesh.material not be cloned when making a copy of Mesh but RenderTarget.textures should be cloned? |
I have reverted the PR via #30572. I've though the change is so obvious that no further discussion was required. The render target class already cloned the image/source but only for the default color attachment, not for all other attachments or depth. That is clearly inconsistent. I would argue that render targets are different than 3D objects. The default should be a deep clone since normally framebuffers hold separate data. Sharing data seems more of an edge case to me that developers still can configure. |
I wonder if it would be worthwhile to differentiate between a clone and a copy in the API? In Rust, for example, Copy types are
So Copy is shallow and does not duplicate any resources. Whereas Clone is:
So Clone could in fact allocate new resources (and it generally does) and that would be a deep copy.
Code that clones RenderTarget currently clones depthTexture. This doesn't however fix the problem with them sharing a single source. So clone on the texture isn't enough either - you have to clone .source. I can't find a clean way to clone Source on a texture. Maybe that should be added? As well as comments in the documentation to make it obvious what users should do if they intent to create a new texture from the existing one? Documentation wording on RenderTarget in not clear on whether that should be a deep or a shallow copy either:
Compare that to the wording on Texture's clone:
|
That is normally not wanted since that would duplicate the texture source leading to redundant texture uploads. That was the reason why I would also not change the semantics of clone since cloning 3D objects is often done on app level and that should not be deep. Otherwise you end up with many duplicated geometries and materials. The implementation of copy and clone methods depends on the use case. If I could start from scratch, I would only add copy/clone methods to the math classes. There was one point where I actually suggested to remove There are use cases where you want to share e.g. the depth across render targets (like for OIT) but in most cases they refer to separate data storage. What you essentially copy/clone is the framebuffer setup but without sharing resources. |
I agree I don't think we should change these semantics. Not to mention this would be a significant breaking change.
Yeah this is the fundamental issue - but it's still the case that at least the "clone" function get a lot of use. Copy is the function that poses conceptual issues in my opinion. The behavior on Object3D is really odd (meaning it adds children to those already there rather than copying fields onto the existing children which can get complicated for a lot of reasons - not that there's better behavior I can think of). A similar conceptual fault is present in RenderTarget, I feel. If you "copy" a render target then all original textures are overwritten (not modified) meaning references can be lost, leading to a memory leak. All to say I think the clone functions are useful on these classes - though I don't think I've ever successfully used the "copy" functions for objects or render targets.
My only issue here is that clone in this case will create new assets that may not be needed and just be replaced by the original references (though I understand they won't have been initialized). Admittedly it is probably the less common use case to want the texture references to be retained on clone. When I look at the code, though, it looks like it could have been a deliberate choice. Adjusting all those textures to be cloned could be a breaking change for some apps, no? |
If #30570 would be merged, it should definitely be noted in the migration guide. But I would rather risk a breakage if we end up with the more consistent setup. If apps are not happy with the default clone, they can implement a custom render target class and overwrite the |
Understood - okay lets merge #30570 but I think we should also make sure to update the docs to be clear that all MRT subtextures and depth texture are cloned, and that users can construct a new render target to share buffers. Thank you for discussing it! |
Description
Cloning a RenderTarget does not create a new Source for the new DepthTexture.
I've encountered this bug while using EffectComposer. If you pass a RenderTarget with depthTexture into EffectComposer, it will clone the depthTexture, but will not update its Source. This results in
GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture
if you use passes that use depth texture.I've found two very similar issues: one two
Reproduction steps
Code
See jsfiddle for the example where that breaks EffectComposer
Live example
https://jsfiddle.net/teu61qyj/3/
P.S. jsfiddle does not print the feedback error for me, but the rendering still breaks
Screenshots
No response
Version
r173
Device
Desktop
Browser
Chrome
OS
Windows
The text was updated successfully, but these errors were encountered: