[2.2] Exception after light baking + PCC probes update

Discussion area about developing with Ogre2 branches (2.1, 2.2 and beyond)
Post Reply
rujialiu
Goblin
Posts: 280
Joined: Mon May 09, 2016 8:21 am
x 33

[2.2] Exception after light baking + PCC probes update

Post by rujialiu »

Hi!

I got this exception:

Code: Select all

11:09:07: OGRE EXCEPTION(1:InvalidStateException): Last frame called map( bAdvanceFrame = false ) but didn't call advanceFrame!!!. in BufferPacked::map at C:\ogremygui\OGRE\OgreMain\src\Vao\OgreBufferPacked.cpp (line 190)
Detail:

Code: Select all

if( //This is a different frame from the last time we called map
                mLastFrameMapped != currentFrame &&
                //map was called, but bAdvanceFrame was not.
                (int)(mLastFrameMapped - mLastFrameMappedAndAdvanced) > 0 )
            {
                OGRE_EXCEPT( Exception::ERR_INVALID_STATE,
                             "Last frame called map( bAdvanceFrame = false ) but "
                             "didn't call advanceFrame!!!.", "BufferPacked::map" );
            }
When the exception occurs, mLastFrameMapped=150, mLastFrameMappedAndAdvanced=149, currentFrame=153 and the next function in the call stack is:

Code: Select all

float* RESTRICT_ALIAS_RETURN HlmsBufferManager::mapNextTexBuffer( CommandBuffer *commandBuffer,
                                                                      size_t minimumSizeBytes )
    {
...

        mRealStartMappedTexBuffer   = reinterpret_cast<float*>(
                                            texBuffer->map( mTexLastOffset,
                                                            texBuffer->getNumElements() - mTexLastOffset, /////////// here
                                                            false ) );
This happens when I do some light bakings and THEN update PCC probes. The light baking loop is something like:

Code: Select all

 for (const auto& action : mLightmapBakingActions) {
	beforeLightBakingAction(action); // change visilibty mask, move camera etc

        sceneManager->updateSceneGraph();

        auto bakingWorkspace = action.worspace;
        bakingWorkspace->_beginUpdate(false);
        bakingWorkspace->_update();
        bakingWorkspace->_endUpdate(false);
        sceneManager->clearFrameData();

        afterLightBakingAction(idx); // restore changed things
    }
Back to the exception-rasing code. In the first bake, currentFrame=150 so mLastFrameMapped changed to 150 too, but mLastFrameMappedAndAdvanced is still 149.

In the second bake in the loop (I have 5 actions in the loop), although (int)(mLastFrameMapped - mLastFrameMappedAndAdvanced) > 0 is true (150>149), but mLastFrameMapped == currentFrame (both 150) so the exception was not raised.

However, after all the baking actions, when updating PCC probes:

Code: Select all

void ParallaxCorrectedCubemap::updateExpensiveCollectedDirtyProbes( uint16 iterationThreshold )
    {
        RenderSystem *renderSystem = mSceneManager->getDestinationRenderSystem();
        HlmsManager *hlmsManager = mRoot->getHlmsManager();

        const uint32 oldVisibilityMask = mSceneManager->getVisibilityMask();
        mSceneManager->setVisibilityMask( 0xffffffff );

        for( size_t i=0; i<mNumCollectedProbes; ++i )
        {
            if( (mCollectedProbes[i]->mDirty || !mCollectedProbes[i]->mStatic) &&
                mCollectedProbes[i]->mNumIterations > iterationThreshold )
            {
                setFinalProbeTo( i );

                for( int j=0; j<mCollectedProbes[i]->mNumIterations; ++j )
                {
                    renderSystem->_beginFrameOnce();
                    mCopyWorkspace->_beginUpdate( true );
                        if( j == 0 )
                            mCollectedProbes[i]->_clearCubemap();
                        mCopyWorkspace->_update();
                        mCollectedProbes[i]->_updateRender(); //////////////////////////////////////here
                    mCopyWorkspace->_endUpdate( true );
the _updateRender() eventually enter HlmsBufferManager::mapNextTexBuffer() again, and then BufferPacked::map() and raised an exception because (int)(mLastFrameMapped - mLastFrameMappedAndAdvanced) > 0 is still true (again 150>149), BUT now currentFrame is 153 so mLastFrameMapped != currentFrame is also true.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4350
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 883
Contact:

Re: [2.2] Exception after light baking + PCC probes update

Post by dark_sylinc »

Looks like HlmsBufferManager::postCommandBufferExecution didn't get called, or HlmsBufferManager::frameEnded got called too early.
Alternatively, it may be possible to fix this issue by calling VaoManager::_update in between.

rujialiu
Goblin
Posts: 280
Joined: Mon May 09, 2016 8:21 am
x 33

Re: [2.2] Exception after light baking + PCC probes update

Post by rujialiu »

dark_sylinc wrote:
Wed Jun 12, 2019 7:26 am
Looks like HlmsBufferManager::postCommandBufferExecution didn't get called, or HlmsBufferManager::frameEnded got called too early.
Alternatively, it may be possible to fix this issue by calling VaoManager::_update in between.
We managed to get a simple repro by slightly modifying the "Texture Baking" demo:

Code: Select all

 .../Tutorial_TextureBaking/Tutorial_TextureBakingGameState.cpp    | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Samples/2.0/Tutorials/Tutorial_TextureBaking/Tutorial_TextureBakingGameState.cpp b/Samples/2.0/Tutorials/Tutorial_TextureBaking/Tutorial_TextureBakingGameState.cpp
index b61f5a66..a982d8f6 100644
--- a/Samples/2.0/Tutorials/Tutorial_TextureBaking/Tutorial_TextureBakingGameState.cpp
+++ b/Samples/2.0/Tutorials/Tutorial_TextureBaking/Tutorial_TextureBakingGameState.cpp
@@ -371,7 +371,7 @@ namespace Demo
         for( size_t i=0; i<c_numAreaLights; ++i )
         {
             createLight( Ogre::Vector3( (i - (c_numAreaLights-1u) * 0.5f) * 10, 4.0f, 0.0f ), i );
-            setupLightTexture( i );
+            //setupLightTexture( i );
         }
 
         mCameraController = new CameraController( mGraphicsSystem, false );
@@ -478,6 +478,12 @@ namespace Demo
         {
             mRenderingMode = RenderingMode::ShowSceneWithBakedTexture;
             updateBakingTexture();
+
+			for (size_t i = 0; i<c_numAreaLights; ++i)
+			{
+				//createLight(Ogre::Vector3((i - (c_numAreaLights - 1u) * 0.5f) * 10, 4.0f, 0.0f), i);
+				setupLightTexture(i);
+			}
             updateRenderingMode();
         }
         else if( arg.keysym.sym == SDLK_F4 )
We're getting the following exception:

Code: Select all

11:01:44: OGRE EXCEPTION(1:InvalidStateException): Last frame called map( bAdvanceFrame = false ) but didn't call advanceFrame!!!. in BufferPacked::map at C:\myguiogre\ogre\OgreMain\src\Vao\OgreBufferPacked.cpp (line 190)

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4350
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 883
Contact:

Re: [2.2] Exception after light baking + PCC probes update

Post by dark_sylinc »

Hi!

I'm taking a look at your repro.

The problem is happening because Tutorial_TextureBakingGameState::updateBakingTexture() initiates compositor rendering (to do the baking) and HlmsBufferManager::frameEnded isn't called because it assumes more rendering will continue happening later (i.e. rendering to the main window).

But when you insert your snippet which sneakily ends up calling VaoManager::_update; this assumption breaks as it is now considered a new frame, and the following needs to be performed:

Code: Select all

sceneManager->_frameEnded();
for( size_t i=0; i<HLMS_MAX; ++i )
{
    Hlms *hlms = hlmsManager->getHlms( static_cast<HlmsTypes>( i ) );
    if( hlms )
        hlms->frameEnded();
}
I am now trying to figure out a more API friendly way to fix this mess because waiting for texture streaming can sneak calls to VaoManager::_update.

rujialiu
Goblin
Posts: 280
Joined: Mon May 09, 2016 8:21 am
x 33

Re: [2.2] Exception after light baking + PCC probes update

Post by rujialiu »

dark_sylinc wrote:
Sun Sep 01, 2019 5:15 pm
I am now trying to figure out a more API friendly way to fix this mess because waiting for texture streaming can sneak calls to VaoManager::_update.
Any update on this? If it's non-trivial to provide a really API friendly way to fix, could you simply wrap these code you mentioned:

Code: Select all

sceneManager->_frameEnded();
for( size_t i=0; i<HLMS_MAX; ++i )
{
    Hlms *hlms = hlmsManager->getHlms( static_cast<HlmsTypes>( i ) );
    if( hlms )
        hlms->frameEnded();
}
Into a function so that we can call it explicitly? If the problem can be solved this way, then great.

zxz
Gremlin
Posts: 160
Joined: Sat Apr 16, 2016 9:25 pm
x 12

Re: [2.2] Exception after light baking + PCC probes update

Post by zxz »

Hello!

I think I've run into an issue related to the one discussed in this thread.

I run into the following assert:

Code: Select all

OgreMain/src/OgreRenderQueue.cpp(876): Assert Failure: 'mRenderingStarted == 0u && "Called RenderQueue::frameEnded mid-render. This may happen if VaoManager::_update got " "called after RenderQueue::renderPassPrepare but before RenderQueue::render returns. Please " "move that VaoManager::_update call outside, otherwise we cannot guarantee rendering will " "be glitch-free, as the BufferPacked buffers from Hlms may be bound at the wrong offset. " "For more info see https://github.com/OGRECave/ogre-next/issues/33 and " "https://forums.ogre3d.org/viewtopic.php?f=25&t=95092#p545907"'
Which was added in the fix of issue 33 (https://github.com/OGRECave/ogre-next/issues/33).

This happens when manually executing a workspace for rendering a dynamic cubemap.

Code: Select all

#0  Ogre::RenderQueue::frameEnded (this=0x2cc1070) at OgreMain/src/OgreRenderQueue.cpp:887
#1  Ogre::SceneManager::_frameEnded (this=0x2cb89a0) at OgreMain/src/OgreSceneManager.cpp:1505
#2  Ogre::Root::_renderingFrameEnded (this=0x1ddcb80) at OgreMain/src/OgreRoot.cpp:1573
#3  Ogre::VaoManager::_update (this=0x22bd630) at OgreMain/src/Vao/OgreVaoManager.cpp:611
#4  Ogre::GL3PlusVaoManager::_update (this=0x22bd630) at RenderSystems/GL3Plus/src/Vao/OgreGL3PlusVaoManager.cpp:1396
#5  Ogre::TextureGpuManager::_waitFor (this=0x273ff70, texture=0xb285200, metadataOnly=false) at OgreMain/src/OgreTextureGpuManager.cpp:3206
#6  Ogre::TextureGpu::waitForData (this=0xb285200) at OgreMain/src/OgreTextureGpu.cpp:988
#7  Ogre::TextureUnitState::ensureLoaded (this=0x2a25ba0, frame=0) at OgreMain/src/OgreTextureUnitState.cpp:1169
#8  Ogre::TextureUnitState::_getTexturePtr (this=0x2a25ba0, frame=0) at OgreMain/src/OgreTextureUnitState.cpp:1044
#9  Ogre::TextureUnitState::_getTexturePtr (this=0x2a25ba0) at OgreMain/src/OgreTextureUnitState.cpp:1035
#10 Ogre::RenderSystem::_setTextureUnitSettings (this=0x1e608b0, texUnit=0, tl=...) at OgreMain/src/OgreRenderSystem.cpp:253
#11 Ogre::HlmsLowLevel::executeCommand (this=0x1e43300, movableObject=0x29909d0, renderable=0x2990910, casterPass=false) at OgreMain/src/OgreHlmsLowLevel.cpp:338
#12 Ogre::HlmsLowLevel::fillBuffersFor (this=0x1e43300, cache=0x4ae6e40, queuedRenderable=..., casterPass=false, lastCacheHash=0, lastTextureHash=0) at OgreMain/src/OgreHlmsLowLevel.cpp:208
#13 Ogre::RenderQueue::renderSingleObject (this=0x2cc1070, pRend=0x2990910, pMovableObject=0x29909d0, rs=0x1e608b0, casterPass=false, dualParaboloid=false) at OgreMain/src/OgreRenderQueue.cpp:862
#14 Ogre::SceneManager::_renderSingleObject (this=0x2cb89a0, pRend=0x2990910, pMovableObject=0x29909d0, casterPass=false, dualParaboloid=false) at OgreMain/src/OgreSceneManager.cpp:4404
#15 Ogre::CompositorPassQuad::execute (this=0x32e0ed0, lodCamera=0x0) at OgreMain/src/Compositor/Pass/PassQuad/OgreCompositorPassQuad.cpp:277
#16 Ogre::CompositorNode::_update (this=0x325cd10, lodCamera=0x0, sceneManager=0x2cb89a0) at OgreMain/src/Compositor/OgreCompositorNode.cpp:890
#17 Ogre::CompositorWorkspace::_update (this=0x325cb50) at OgreMain/src/Compositor/OgreCompositorWorkspace.cpp:791
This code path seems to run directly into the case described in the assert message. renderSingleObject signals that rendering has started, after which the loading of the Quad's texture triggers VaoManager::_update, triggering the assertion.

What is the proper way of solving this issue?

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4350
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 883
Contact:

Re: [2.2] Exception after light baking + PCC probes update

Post by dark_sylinc »

This is an Ogre bug. Working on it...

In the meantime, before updating that workspace manually, call:

Code: Select all

mTextureGpuManager->waitForStreamingCompletion();
Update: Fix pushed.
Let me know if this fixes the issue (without the workaround mentioned above)

zxz
Gremlin
Posts: 160
Joined: Sat Apr 16, 2016 9:25 pm
x 12

Re: [2.2] Exception after light baking + PCC probes update

Post by zxz »

Thanks :) The fix works.

Ps. the following assert can be reached when a cubemap fails to load due to an exception:

Code: Select all

OgreMain/src/OgreImage2.cpp:265: void Ogre::Image2::loadDynamicImage(void*, Ogre::uint32, Ogre::uint32, Ogre::uint32, Ogre::TextureTypes::TextureTypes, Ogre::PixelFormatGpu, bool, Ogre::uint8): Assertion `(textureType != TextureTypes::TypeCube || depthOrSlices == 6u) && "depthOrSlices must be 6!"' failed.
The fallback tries to load mErrorFallbackTexData with depthOrSlices==1 and TextureTypes::TypeCube.

In my case the DDS didn't load because OgreDDSCodec2 seems to support a lot fewer formats than OgreDDSCodec did before. Any specific reason for this? Adding a case to convertDXToOgreFormat seems to be enough to fix this in my case. (Edit: I can see that the format I need (10, PFG_RGBA16_FLOAT), has already been added in v2-2-irradiance-field)

Post Reply