Giter Club home page Giter Club logo

Comments (9)

moudgils avatar moudgils commented on August 25, 2024

Looks like the code needs to handle incorrect or incomplete assets gracefully. Are you able to add a null check, possibly add an assert and exit out of the method to see if that fixes the crash itself. It is possible that the asset may not render correctly. The hope here is that the developer will see that the asset is missing information and address that as needed.

from o3de.

moudgils avatar moudgils commented on August 25, 2024

Tagging @nick-l-o3de as you were also looking at similar issue whereby creating skinned mesh code doesnt handle bad/incomplete data properly.

from o3de.

realJavabot avatar realJavabot commented on August 25, 2024

Wanted to add that this can also happen if your mesh has an object not part of the skin.

from o3de.

realJavabot avatar realJavabot commented on August 25, 2024

The initial load appears to handle the unloaded asset correctly, but it causes some issues immediately after:

<21:49:26> Trace::Assert
 D:\o3de\Code\Framework\AzCore\AzCore/Asset/AssetCommon.h(339): (34440) 'class AZ::RPI::BufferAsset *__cdecl AZ::Data::Asset<class AZ::RPI::BufferAsset>::operator ->(void) const'

<21:49:26> Asset {4CE2FA19-4EF1-5C82-89CF-0EC68ABC0E44}:10ef8d28 (assets/low_poly_human_lod0_skin_jointindices0.fbx.azbuffer) is not loaded

<21:49:26> ------------------------------------------------

<21:49:28> D:\o3de\Code\Framework\AzCore\AzCore\Asset\AssetCommon.h (339) : AZ::Data::Asset<AZ::RPI::BufferAsset>::operator->

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\ActorAsset.cpp (215) : AZ::Render::CreateSkinnedMeshInputFromActor

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActor.cpp (50) : AZ::Render::AtomActor::FindOrCreateSkinnedMeshInputBuffers

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (456) : AZ::Render::AtomActorInstance::Create

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (193) : AZ::Render::AtomActorInstance::Activate

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (62) : AZ::Render::AtomActorInstance::AtomActorInstance

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomBackend.cpp (35) : AZ::Render::AtomBackend::CreateActorInstance

<21:49:28> D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (1018) : EMotionFX::Integration::EditorActorComponent::CheckActorCreation

<21:49:28> D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (700) : EMotionFX::Integration::EditorActorComponent::OnTick

<21:49:28> D:\o3de\Code\Framework\AzCore\AzCore\EBus\Internal\BusContainer.h (1360) : AZ::Internal::EBusContainer<AZ::TickEvents,AZ::TickEvents,0,2>::Dispatcher<AZ::EBus<AZ::TickEvents,AZ::TickEvents> >::Broadcast<void (__cdecl AZ::TickEvents::*)(float,AZ::ScriptTi

<21:49:28> D:\o3de\Code\Framework\AzCore\AzCore\Component\ComponentApplication.cpp (1645) : AZ::ComponentApplication::Tick

<21:49:28> D:\o3de\Code\Editor\GameEngine.cpp (765) : CGameEngine::Update

<21:49:28> D:\o3de\Code\Editor\CryEdit.cpp (2256) : CCryEditApp::IdleProcessing

<21:49:28> D:\o3de\Code\Editor\CryEdit.cpp (2153) : CCryEditApp::OnIdle

<21:49:28> D:\o3de\Code\Editor\Core\QtEditorApplication.cpp (319) : Editor::EditorQtApplication::maybeProcessIdle

<21:49:28> 00007FF919FCF72A (Qt5Core) : QTimer::timeout

<21:49:28> 00007FF919FC82DD (Qt5Core) : QObject::event

<21:49:28> 00007FF9355449A1 (Qt5Widgets) : QApplicationPrivate::notify_helper

<21:49:28> 00007FF935543A23 (Qt5Widgets) : QApplication::notify

<21:49:28> 00007FF919FA17CB (Qt5Core) : QCoreApplication::notifyInternal2

<21:49:28> 00007FF919FEC1B9 (Qt5Core) : QEventDispatcherWin32Private::sendTimerEvent

<21:49:28> 00007FF919FEA5E9 (Qt5Core) : QEventDispatcherWin32::event

<21:49:28> 00007FF9355449A1 (Qt5Widgets) : QApplicationPrivate::notify_helper

<21:49:28> 00007FF935543A23 (Qt5Widgets) : QApplication::notify

<21:49:28> 00007FF919FA17CB (Qt5Core) : QCoreApplication::notifyInternal2

<21:49:28> ==================================================================

<21:49:28> ====Assert added to ignore list by spec and verbosity setting.====

<21:49:28> (Exit) - Exception with exit code: 0xc0000005
<21:49:28> (Exit) - D:\o3de\Code\Legacy\CrySystem\DebugCallStack.cpp (229) : DebugCallStack::handleException

<21:49:28> (Exit) - 00007FF9EF2FD827 (KERNELBASE) : UnhandledExceptionFilter

<21:49:28> (Exit) - 00007FF9F1535898 (ntdll) : memset

<21:49:28> (Exit) - 00007FF9F151CE56 (ntdll) : _C_specific_handler

<21:49:28> (Exit) - 00007FF9F153292F (ntdll) : _chkstk

<21:49:28> (Exit) - 00007FF9F14E2554 (ntdll) : RtlRaiseException

<21:49:28> (Exit) - 00007FF9F153143E (ntdll) : KiUserExceptionDispatcher

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\ActorAsset.cpp (215) : AZ::Render::CreateSkinnedMeshInputFromActor

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActor.cpp (50) : AZ::Render::AtomActor::FindOrCreateSkinnedMeshInputBuffers

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (456) : AZ::Render::AtomActorInstance::Create

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (193) : AZ::Render::AtomActorInstance::Activate

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (62) : AZ::Render::AtomActorInstance::AtomActorInstance

<21:49:28> (Exit) - D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomBackend.cpp (35) : AZ::Render::AtomBackend::CreateActorInstance

<21:49:28> (Exit) - D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (1018) : EMotionFX::Integration::EditorActorComponent::CheckActorCreation

<21:49:28> (Exit) - D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (700) : EMotionFX::Integration::EditorActorComponent::OnTick

<21:49:28> (Exit) - D:\o3de\Code\Framework\AzCore\AzCore\EBus\Internal\BusContainer.h (1360) : AZ::Internal::EBusContainer<AZ::TickEvents,AZ::TickEvents,0,2>::Dispatcher<AZ::EBus<AZ::TickEvents,AZ::TickEvents> >::Broadcast<void (__cdecl AZ::TickEvents::*)(float,AZ::ScriptTi

<21:49:28> (Exit) - D:\o3de\Code\Framework\AzCore\AzCore\Component\ComponentApplication.cpp (1645) : AZ::ComponentApplication::Tick

<21:49:28> (Exit) - D:\o3de\Code\Editor\GameEngine.cpp (765) : CGameEngine::Update

<21:49:28> (Exit) - D:\o3de\Code\Editor\CryEdit.cpp (2256) : CCryEditApp::IdleProcessing

<21:49:28> (Exit) - D:\o3de\Code\Editor\CryEdit.cpp (2153) : CCryEditApp::OnIdle

<21:49:28> (Exit) - D:\o3de\Code\Editor\Core\QtEditorApplication.cpp (319) : Editor::EditorQtApplication::maybeProcessIdle

<21:49:28> (Exit) - 00007FF919FCF72A (Qt5Core) : QTimer::timeout

<21:49:28> (Exit) - 00007FF919FC82DD (Qt5Core) : QObject::event

<21:49:28> (Exit) - 00007FF9355449A1 (Qt5Widgets) : QApplicationPrivate::notify_helper

<21:49:28> (Exit) - 00007FF935543A23 (Qt5Widgets) : QApplication::notify

<21:49:28> 00007FF9EF2FD827 (KERNELBASE) : UnhandledExceptionFilter

<21:49:28> 00007FF9F1535898 (ntdll) : memset

<21:49:28> 00007FF9F151CE56 (ntdll) : _C_specific_handler

<21:49:28> 00007FF9F153292F (ntdll) : _chkstk

<21:49:28> 00007FF9F14E2554 (ntdll) : RtlRaiseException

<21:49:28> 00007FF9F153143E (ntdll) : KiUserExceptionDispatcher

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\ActorAsset.cpp (215) : AZ::Render::CreateSkinnedMeshInputFromActor

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActor.cpp (50) : AZ::Render::AtomActor::FindOrCreateSkinnedMeshInputBuffers

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (456) : AZ::Render::AtomActorInstance::Create

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (193) : AZ::Render::AtomActorInstance::Activate

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomActorInstance.cpp (62) : AZ::Render::AtomActorInstance::AtomActorInstance

<21:49:28> D:\o3de\Gems\AtomLyIntegration\EMotionFXAtom\Code\Source\AtomBackend.cpp (35) : AZ::Render::AtomBackend::CreateActorInstance

<21:49:28> D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (1018) : EMotionFX::Integration::EditorActorComponent::CheckActorCreation

<21:49:28> D:\o3de\Gems\EMotionFX\Code\Source\Integration\Editor\Components\EditorActorComponent.cpp (700) : EMotionFX::Integration::EditorActorComponent::OnTick

<21:49:28> D:\o3de\Code\Framework\AzCore\AzCore\EBus\Internal\BusContainer.h (1360) : AZ::Internal::EBusContainer<AZ::TickEvents,AZ::TickEvents,0,2>::Dispatcher<AZ::EBus<AZ::TickEvents,AZ::TickEvents> >::Broadcast<void (__cdecl AZ::TickEvents::*)(float,AZ::ScriptTi

<21:49:28> D:\o3de\Code\Framework\AzCore\AzCore\Component\ComponentApplication.cpp (1645) : AZ::ComponentApplication::Tick

<21:49:28> D:\o3de\Code\Editor\GameEngine.cpp (765) : CGameEngine::Update

<21:49:28> D:\o3de\Code\Editor\CryEdit.cpp (2256) : CCryEditApp::IdleProcessing

<21:49:28> D:\o3de\Code\Editor\CryEdit.cpp (2153) : CCryEditApp::OnIdle

<21:49:28> D:\o3de\Code\Editor\Core\QtEditorApplication.cpp (319) : Editor::EditorQtApplication::maybeProcessIdle

<21:49:28> 00007FF919FCF72A (Qt5Core) : QTimer::timeout

<21:49:28> 00007FF919FC82DD (Qt5Core) : QObject::event

<21:49:28> 00007FF9355449A1 (Qt5Widgets) : QApplicationPrivate::notify_helper

<21:49:28> 00007FF935543A23 (Qt5Widgets) : QApplication::notify

<21:49:28> 00007FF919FA17CB (Qt5Core) : QCoreApplication::notifyInternal2```

from o3de.

nick-l-o3de avatar nick-l-o3de commented on August 25, 2024

This is possibly fixed by #18056 - I will retest once that ends up in development.

from o3de.

nick-l-o3de avatar nick-l-o3de commented on August 25, 2024

This is not fixed by 18056, there are other related issues.

from o3de.

nick-l-o3de avatar nick-l-o3de commented on August 25, 2024

I reproed it by duplicating the entity, still investigating. When I duplicate it, it immediately crashes and it crashes on this line:

// Reserve enough memory for the default/common case. Use the element count from the main source buffer
blendIndexBufferData.reserve(indicesBuffAssetView->GetBufferAsset()->GetBufferViewDescriptor().m_elementCount);
blendWeightBufferData.reserve(weightsBuffAssetView->GetBufferAsset()->GetBufferViewDescriptor().m_elementCount);

because GetBufferAsset() returns null. The asset is valid (as in, it has an asset id) but its state is NOT LOADED and ptr is null.

As far as I can tell so far, the actor asset is whole and complete, but the actor has an emotionfx actor piece, and an atom render actor instance (m_renderActorInstance). The atom render actor instance for the duplicate has all the data (lods, meshes, models, etc, but has no data (and its not loaded) in the actual stream assets for its lod.

This is weird since the thing is set to "pre-load" so it should be present no matter what, assuming it was loaded from a parent that was queue loaded - to be more specific here, if an asset is loaded from disk, and it encounters a sub-asset as part of the asset data, the sub-asset is checked to see what load setting it has. If its "no load" its completely manual, "queue load" will start it loading async in the background, and "pre-load" makes it so that the current loading thread basically stops what its doing and instead loads the child asset before continuing. Meaning that the asset for the render actor shouldn't ever have any "empty" unloaded buffer assets since they are marked as preload.

from o3de.

nick-l-o3de avatar nick-l-o3de commented on August 25, 2024

So this happens only when an asset is reloaded. The Actor asset has a weird way of reloading, in that it ignores the new actor asset handed to it in the OnAssetReloaded() call, and instead, calls DestroyActorInstance and m_actorAsset.Release() and then waits for the Asset Unloaded function to be called. DestroyActorInstance also deletes the render actor instance, in which all the refs to the actor render model might also be destroyed.

This is flawed in a number of ways, not least of which, Other things might have refs to the old data (who knows what - previewers, emotionfx itself, things that are not also EditorActorComponents) and will not release their refs, which will cause the data to not be Unloaded, ever.

But assuming that doesn't happen, and everything in the entire system drops its refcounted refs on the AZ::Asset, all existing EditorActorComponent in the scene will get an OnAssetUnloaded on the same frame.

They will get all the direct dependencies of the actor asset, and find the ModelAsset (as in, atom model). They will then call ReloadModel (which thankfully internally de-duplicates the reload calls), and starts the reload, which seems to be quite a complex system (see ModelReloader.cpp) doing things in layers. Presumably the job here is to finish loading everything, before the callback to m_actorAsset.QueueLoad() is invoked.

But somehow, when we get here, instead, most of the model data is loaded, but the stream buffers for the lods are not. I'm not sure why this only happens on reload, but theres a few things that could be done here.

One would be to make it so that the actor forbids auto-reload of its actor asset time by updating the actor asset handler to return false for the "can I automatically reload" bool override. Since it clearly wants to handle itself. Then the actor components can listen to the "asset changed on disk" bus instead, and do the same thing (that is, drop their ref and load a new one) so that we aren't wasting loads. Unless we do this, then whats going to happen is that the new actor will actually automatically reload and only after its fully finished loading, does it offer it to you in OnAssetReloaded() which is a waste, since it dose not pin the newly loaded one.

Secondly, we need to figure out why the model lods streambuffer assets are not loaded on reload. They are not invalid - they have a valid asset name, assetid, state (its "not loaded"), its just... well, not loaded at all at reload time. Perhaps a bug with the AssetReloader?

The other weird thing here is that the Model Reloader does seem to go thru the process of reloading everything, but the Actor Editor Component listens for the callback (which has the only refcounted model asset in existence) by throwing away the refcount, ie

 [this](AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset)
 {
     m_actorAsset.QueueLoad();
 });

note that this callback happens on the tickbus later, and does not "pin" modelAsset or inc its refcount, effectively throwing it away. This will cause modelAsset to unload unless something else is pinning it in memory somehow.

from o3de.

nick-l-o3de avatar nick-l-o3de commented on August 25, 2024

Further information here, its nothing to do with reload.
easy repro 100% is

  1. load a scene up (it can becompletely empty)
  2. drop any actor in
  3. Open the FBX settings panel for the actor's asset
  4. Hit save
  5. Duplicate the actor

It appears to be becuase the PREVIEW WIDGET registers the mesh with the mesh feature processor, and does so in a way that doesn't ask the feature processor to preserve the buffer assets (ie, the lod's tangents, etc). The mesh feature processor drops the ref of those assets to 0 and they unload.

The next time you duplicate that actor, it is missing the data. Note that its still a mystery why - the actor calls AcquireMesh on the feature processor with a flag that makes it keep the buffer, so its refcount should increase each actor in the scene, but somehow, when the previewer gets it, its refcount goes from 1 to 0, rather than 2 to 1.

from o3de.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.