Fix editor hang on level load (#6323)

Make View::SortFinalizedDrawLists use child jobs so they don't block the worker thread from doing other work while waiting.
Implement a TaskGraph version of the view draw list sort.
Fix a misc bug where the scene was waiting on a task graph event twice and so hanging.
Enable MeshFeatureProcessor::Simulate to be able to use jobs when no parent job is specified because the parent job is a task.

Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com>
This commit is contained in:
rgba16f
2021-12-10 15:03:06 -06:00
committed by GitHub
parent 0ff94f4e6e
commit be0b034c43
4 changed files with 87 additions and 16 deletions
@@ -123,11 +123,26 @@ namespace AZ
}
};
Job* executeGroupJob = aznew JobFunction<decltype(jobLambda)>(jobLambda, true, nullptr); // Auto-deletes
parentJob->StartAsChild(executeGroupJob);
if (parentJob)
{
parentJob->StartAsChild(executeGroupJob);
}
else
{
executeGroupJob->SetDependent(&jobCompletion);
executeGroupJob->Start();
}
}
{
AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: Simulate: WaitForChildren");
parentJob->WaitForChildren();
if (parentJob)
{
parentJob->WaitForChildren();
}
else
{
jobCompletion.StartAndWaitForCompletion();
}
}
m_forceRebuildDrawPackets = false;
@@ -24,6 +24,9 @@ class MaskedOcclusionCulling;
namespace AZ
{
// forward declares
class Job;
class TaskGraphEvent;
namespace RHI
{
class FrameScheduler;
@@ -102,7 +105,8 @@ namespace AZ
//! Finalize draw lists in this view. This function should only be called when all
//! draw packets for current frame are added.
void FinalizeDrawLists();
void FinalizeDrawListsJob(AZ::Job* parentJob);
void FinalizeDrawListsTG(AZ::TaskGraphEvent& finalizeDrawListsTGEvent);
bool HasDrawListTag(RHI::DrawListTag drawListTag);
@@ -142,7 +146,8 @@ namespace AZ
View(const AZ::Name& name, UsageFlags usage);
//! Sorts the finalized draw lists in this view
void SortFinalizedDrawLists();
void SortFinalizedDrawListsJob(AZ::Job* parentJob);
void SortFinalizedDrawListsTG(AZ::TaskGraphEvent& finalizeDrawListsTGEvent);
//! Sorts a drawList using the sort function from a pass with the corresponding drawListTag
void SortDrawList(RHI::DrawList& drawList, RHI::DrawListTag tag);
+11 -6
View File
@@ -114,6 +114,7 @@ namespace AZ
if (m_taskGraphActive)
{
WaitAndCleanTGEvent(AZStd::move(m_simulationFinishedTGEvent));
m_simulationFinishedTGEvent.reset();
}
else
{
@@ -383,7 +384,9 @@ namespace AZ
simulationTGDesc,
[this, featureProcessor]()
{
featureProcessor->Simulate(m_simulatePacket);
FeatureProcessor::SimulatePacket jobPacket = m_simulatePacket;
jobPacket.m_parentJob = nullptr;
featureProcessor->Simulate(jobPacket);
});
}
simulationTG.Detach();
@@ -423,6 +426,7 @@ namespace AZ
if (m_taskGraphActive)
{
WaitAndCleanTGEvent(AZStd::move(m_simulationFinishedTGEvent));
m_simulationFinishedTGEvent.reset();
}
else
{
@@ -609,9 +613,9 @@ namespace AZ
{
finalizeDrawListsTG.AddTask(
finalizeDrawListsTGDesc,
[view]()
[view, &finalizeDrawListsTGEvent]()
{
view->FinalizeDrawLists();
view->FinalizeDrawListsTG(finalizeDrawListsTGEvent);
});
}
finalizeDrawListsTG.Submit(&finalizeDrawListsTGEvent);
@@ -623,9 +627,9 @@ namespace AZ
AZ::JobCompletion* finalizeDrawListsCompletion = aznew AZ::JobCompletion();
for (auto& view : m_renderPacket.m_views)
{
const auto finalizeDrawListsLambda = [view]()
const auto finalizeDrawListsLambda = [view](AZ::Job& job)
{
view->FinalizeDrawLists();
view->FinalizeDrawListsJob(&job);
};
AZ::Job* finalizeDrawListsJob = AZ::CreateJobFunction(AZStd::move(finalizeDrawListsLambda), true, nullptr); //auto-deletes
@@ -642,6 +646,7 @@ namespace AZ
if (m_taskGraphActive)
{
WaitAndCleanTGEvent(AZStd::move(m_simulationFinishedTGEvent));
m_simulationFinishedTGEvent.reset();
}
else
{
@@ -743,7 +748,7 @@ namespace AZ
{
for (auto& view : m_renderPacket.m_views)
{
view->FinalizeDrawLists();
view->FinalizeDrawListsJob(nullptr);
}
}
else
+52 -6
View File
@@ -21,6 +21,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Jobs/JobCompletion.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/Task/TaskGraph.h>
#include <Atom_RPI_Traits_Platform.h>
#if AZ_TRAIT_MASKED_OCCLUSION_CULLING_SUPPORTED
@@ -253,14 +254,45 @@ namespace AZ
return m_drawListContext.GetList(drawListTag);
}
void View::FinalizeDrawLists()
void View::FinalizeDrawListsTG(AZ::TaskGraphEvent& finalizeDrawListsTGEvent)
{
AZ_PROFILE_SCOPE(RPI, "View: FinalizeDrawLists");
m_drawListContext.FinalizeLists();
SortFinalizedDrawLists();
SortFinalizedDrawListsTG(finalizeDrawListsTGEvent);
}
void View::FinalizeDrawListsJob(AZ::Job* parentJob)
{
AZ_PROFILE_SCOPE(RPI, "View: FinalizeDrawLists");
m_drawListContext.FinalizeLists();
SortFinalizedDrawListsJob(parentJob);
}
void View::SortFinalizedDrawLists()
void View::SortFinalizedDrawListsTG(AZ::TaskGraphEvent& finalizeDrawListsTGEvent)
{
AZ_PROFILE_SCOPE(RPI, "View: SortFinalizedDrawLists");
RHI::DrawListsByTag& drawListsByTag = m_drawListContext.GetMergedDrawListsByTag();
AZ::TaskGraph drawListSortTG;
AZ::TaskDescriptor drawListSortTGDescriptor{"RPI_View_SortFinalizedDrawLists", "Graphics"};
for (size_t idx = 0; idx < drawListsByTag.size(); ++idx)
{
if (drawListsByTag[idx].size() > 1)
{
drawListSortTG.AddTask(drawListSortTGDescriptor, [this, &drawListsByTag, idx]()
{
AZ_PROFILE_SCOPE(RPI, "View: SortDrawList Task");
SortDrawList(drawListsByTag[idx], RHI::DrawListTag(idx));
});
}
}
if (!drawListSortTG.IsEmpty())
{
drawListSortTG.Detach();
drawListSortTG.Submit(&finalizeDrawListsTGEvent);
}
}
void View::SortFinalizedDrawListsJob(AZ::Job* parentJob)
{
AZ_PROFILE_SCOPE(RPI, "View: SortFinalizedDrawLists");
RHI::DrawListsByTag& drawListsByTag = m_drawListContext.GetMergedDrawListsByTag();
@@ -276,11 +308,25 @@ namespace AZ
SortDrawList(drawListsByTag[idx], RHI::DrawListTag(idx));
};
Job* jobSortDrawList = aznew JobFunction<decltype(jobLambda)>(jobLambda, true, nullptr); // Auto-deletes
jobSortDrawList->SetDependent(&jobCompletion);
jobSortDrawList->Start();
if (parentJob)
{
parentJob->StartAsChild(jobSortDrawList);
}
else
{
jobSortDrawList->SetDependent(&jobCompletion);
jobSortDrawList->Start();
}
}
}
jobCompletion.StartAndWaitForCompletion();
if (parentJob)
{
parentJob->WaitForChildren();
}
else
{
jobCompletion.StartAndWaitForCompletion();
}
}
void View::SortDrawList(RHI::DrawList& drawList, RHI::DrawListTag tag)