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

[osg3.6] prevent immutability setting when textureobject is taken from orphans #934

Conversation

mp3butcher
Copy link
Contributor

@mp3butcher mp3butcher commented Mar 25, 2020

a quick fix for #935 a minor problem that affect master too

@mp3butcher mp3butcher changed the title prevent immutability setting when textureobject is taken from orphans [osg3.6] prevent immutability setting when textureobject is taken from orphans Mar 25, 2020
@mp3butcher mp3butcher force-pushed the orphanalreadyimmutable branch 5 times, most recently from 04478b5 to 4e7a67d Compare March 26, 2020 01:16
@AnyOldName3
Copy link
Contributor

I just got around to actually testing this, and it does indeed fix the issue in OpenMW, as anticipated. I imagine there'll be some tweaking before this is actually merged (setted isn't a word, for example), but something based on this should be good.

@openscenegraph
Copy link
Owner

I have started looking at the PR and the underlying code. Use of _immutableSetted variable is rather awkward in terms of language. We'll need a more appropriate name if this variable is required.

Looking at Texture::TextureObject there is already an _allocated member variable which sounds like there is functionality overlap with _immutableSetted. The code path contain the glTextureStorage2D does set the Allocated parameters which is possibly a bit odd. The underlying code goes many years back before glTextureStoage2D code was introduced, it might be was these new features were introduced not everything has been evolved correctly w.r.t working with the old features as well as the new.

I'm coming to the topic a bit cold so don't have any fully formed opinions yet. One of my first thoughts are to explore whether the TextureObject::_allocated/setAllocated() functionality is something we can use to decided whether the glTextureStorage2D should be called or not. If so then a check against if (texturObject-isAllocated()) would be appropriate along with correct calling of setAllocated().

Thoughts?

@AnyOldName3
Copy link
Contributor

I think texture allocation versus immutable allocation are different concerns, even if they're related, so even if they can be combined, it'll potentially be misleading. glTexImage allocates a texture, but not immutably, so it can be reallocated again later.

@openscenegraph
Copy link
Owner

openscenegraph commented Apr 29, 2020 via email

@mp3butcher
Copy link
Contributor Author

mp3butcher commented May 1, 2020

My hunch is that proper use of the allocated flag and sizing of
TextureObject members should be sufficient.

_allocated could serve the propose if we remove _allocated=true from TextureObject::setAllocated and set it true out of TextureObject scope (in TextureXXX::apply)
@robertosfield Is it what you want?
M guess is packing allocated and immutabilitySet in a bitfield or refactoring (gloup) to take into account immutability are more sensible

@robertosfield
Copy link
Collaborator

@mp3butcher sometimes you perplex me:

"_allocated could serve the propose if we remove _allocated=true from TextureObject::setAllocated"

I can't think why you'd ever want to change a feature behavior so it doesn't behave in the most obvious way and in the way it was designed for. setAllocated should set _allocated = true, because it's the most logically sound thing to do with this naming of methods.

All I'm asking here is whether the problem code block in question, the on with the glTexStorage2D call is missing a check if (textureObject->isAllocated()) and missing a corresponding setAllocated().

A little above the problem section we have a code block:

       if (textureObject->isAllocated() && image->supportsTextureSubloading())
        {
            //OSG_NOTICE<<"Reusing texture object"<<std::endl;
            applyTexImage2D_subload(state,GL_TEXTURE_2D,image.get(),
                                 _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
        }
        else
        {
            //OSG_NOTICE<<"Creating new texture object"<<std::endl;
            applyTexImage2D_load(state,GL_TEXTURE_2D,image.get(),
                                 _textureWidth, _textureHeight, _numMipmapLevels);

            textureObject->setAllocated(true);
        }

Could it simply be that the glTexStorage2D code path is missing that this type of usage? FYI, I'm not the original author of the glTexStorage2D so it might be that the original contributor of it didn't realize about the Allocated support in TextureObject and I didn't spot the problem when merging.

I don't have a test case to run and see the problem happening so I'm working a bit blind on this particular bug report.

@mp3butcher
Copy link
Contributor Author

tested and ok for merging

@robertosfield
Copy link
Collaborator

@mp3butcher Changes look good :-)

@openscenegraph openscenegraph merged commit 6ca2487 into openscenegraph:OpenSceneGraph-3.6 May 3, 2020
@robertosfield
Copy link
Collaborator

robertosfield commented May 3, 2020 via email

@AnyOldName3
Copy link
Contributor

I think there's potentially a race condition where this can still happen. I've got an APITrace (unfortunately 16 GB long because it reproduces really rarely when APITrace is attached) where glTexStorage2D gets called on a texture it's already been called on, despite using an OSG build featuring this PR's changes. These are the interesting calls:

242310476 @1 glGenTextures(n = 1, textures = [228])
242310477 @1 glBindTexture(target = GL_TEXTURE_2D, texture = 228)
255218421 @1 glDeleteTextures(n = 1, textures = [228])
255689975 @1 glGenTextures(n = 1, textures = [228])
255689976 @1 glBindTexture(target = GL_TEXTURE_2D, texture = 228)
255689986 @1 glTexStorage2D(target = GL_TEXTURE_2D, levels = 1, internalformat = GL_RGB8, width = 512, height = 512)
255689996 @1 wglSwapBuffers(hdc = 0xffffffffed010d73) = TRUE
255690042 @1 glFramebufferTexture2D(target = GL_DRAW_FRAMEBUFFER, attachment = GL_COLOR_ATTACHMENT0, textarget = GL_TEXTURE_2D, texture = 228, level = 0)
269792082 @1 glBindTexture(target = GL_TEXTURE_2D, texture = 228)
269792092 @1 glTexStorage2D(target = GL_TEXTURE_2D, levels = 1, internalformat = GL_RGB8, width = 512, height = 512)
269792095 @1 glFramebufferTexture2D(target = GL_DRAW_FRAMEBUFFER, attachment = GL_COLOR_ATTACHMENT0, textarget = GL_TEXTURE_2D, texture = 228, level = 0)

I think what's happening is possibly an incremental compile operation getting split across two frames, but I'm not entirely sure how _allocated could end up unset because of that.

@AnyOldName3
Copy link
Contributor

It's harder to reproduce with a build made from a more recent commit, though, so either some changes have hidden it, or it's been fixed.

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.

None yet

5 participants