FIRE-31326 - Fix crash thread contention crash
Crash caused by DD stepping and AutoTune both hacking the RenderFarClip. Added a proxy tunables structure to allow the main thread to tweak the tunables while the work is still done on the perf thread.master
parent
5b1282d35e
commit
105f20b055
|
|
@ -111,3 +111,5 @@ compile_commands.json
|
||||||
# ignore tracy for now
|
# ignore tracy for now
|
||||||
indra/tracy
|
indra/tracy
|
||||||
firestorm.code-workspace
|
firestorm.code-workspace
|
||||||
|
|
||||||
|
.cache/clangd/index/
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,12 @@ namespace FSPerfStats
|
||||||
std::atomic<int64_t> tunedAvatars{0};
|
std::atomic<int64_t> tunedAvatars{0};
|
||||||
U32 targetFPS; // desired FPS
|
U32 targetFPS; // desired FPS
|
||||||
U64 renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
|
U64 renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
|
||||||
U32 fpsTuningStrategy{0}; // linked to FSTuningFPSStrategy
|
|
||||||
U32 lastGlobalPrefChange{0};
|
U32 lastGlobalPrefChange{0};
|
||||||
std::mutex bufferToggleLock{};
|
std::mutex bufferToggleLock{};
|
||||||
bool autoTune{false};
|
bool autoTune{false};
|
||||||
|
|
||||||
|
Tunables tunables;
|
||||||
|
|
||||||
std::atomic<int> StatsRecorder::writeBuffer{0};
|
std::atomic<int> StatsRecorder::writeBuffer{0};
|
||||||
bool StatsRecorder::collectionEnabled{true};
|
bool StatsRecorder::collectionEnabled{true};
|
||||||
LLUUID StatsRecorder::focusAv{LLUUID::null};
|
LLUUID StatsRecorder::focusAv{LLUUID::null};
|
||||||
|
|
@ -61,6 +62,14 @@ namespace FSPerfStats
|
||||||
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::max{ {} };
|
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::max{ {} };
|
||||||
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::sum{ {} };
|
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::sum{ {} };
|
||||||
|
|
||||||
|
void Tunables::applyUpdates()
|
||||||
|
{
|
||||||
|
assert_main_thread();
|
||||||
|
if( tuningFlag & NonImposters ){ gSavedSettings.setU32("IndirectMaxNonImpostors", nonImposters); };
|
||||||
|
if( tuningFlag & ReflectionDetail ){ gSavedSettings.setS32("RenderReflectionDetail", reflectionDetail); };
|
||||||
|
if( tuningFlag & FarClip ){ gSavedSettings.setF32("RenderFarClip", farClip); };
|
||||||
|
resetChanges();
|
||||||
|
}
|
||||||
|
|
||||||
StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run)
|
StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run)
|
||||||
{
|
{
|
||||||
|
|
@ -175,7 +184,7 @@ namespace FSPerfStats
|
||||||
sum[writeBuffer][i].fill(0);
|
sum[writeBuffer][i].fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and now adjust the visuals.
|
// and now adjust the proxy vars so that the main thread can adjust the visuals.
|
||||||
if(autoTune)
|
if(autoTune)
|
||||||
{
|
{
|
||||||
updateAvatarParams();
|
updateAvatarParams();
|
||||||
|
|
@ -280,6 +289,7 @@ namespace FSPerfStats
|
||||||
static LLCachedControl<F32> impostorDistance(gSavedSettings, "FSAutoTuneImpostorFarAwayDistance");
|
static LLCachedControl<F32> impostorDistance(gSavedSettings, "FSAutoTuneImpostorFarAwayDistance");
|
||||||
static LLCachedControl<bool> impostorDistanceTuning(gSavedSettings, "FSAutoTuneImpostorByDistEnabled");
|
static LLCachedControl<bool> impostorDistanceTuning(gSavedSettings, "FSAutoTuneImpostorByDistEnabled");
|
||||||
static LLCachedControl<U32> maxNonImpostors (gSavedSettings, "IndirectMaxNonImpostors");
|
static LLCachedControl<U32> maxNonImpostors (gSavedSettings, "IndirectMaxNonImpostors");
|
||||||
|
static LLCachedControl<U32> fpsTuningStrategy (gSavedSettings, "FSTuningFPSStrategy");
|
||||||
|
|
||||||
if(impostorDistanceTuning)
|
if(impostorDistanceTuning)
|
||||||
{
|
{
|
||||||
|
|
@ -288,7 +298,7 @@ namespace FSPerfStats
|
||||||
auto count = countNearbyAvatars(std::min(drawDistance, impostorDistance));
|
auto count = countNearbyAvatars(std::min(drawDistance, impostorDistance));
|
||||||
if( count != maxNonImpostors )
|
if( count != maxNonImpostors )
|
||||||
{
|
{
|
||||||
gSavedSettings.setU32("IndirectMaxNonImpostors", (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER);
|
tunables.updateNonImposters( (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER );
|
||||||
LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(drawDistance, impostorDistance) << "m of the camera" << LL_ENDL;
|
LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(drawDistance, impostorDistance) << "m of the camera" << LL_ENDL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -339,13 +349,13 @@ namespace FSPerfStats
|
||||||
// we cannnot do this by avatar adjustment alone.
|
// we cannnot do this by avatar adjustment alone.
|
||||||
if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > 10) // give changes a short time to take effect.
|
if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > 10) // give changes a short time to take effect.
|
||||||
{
|
{
|
||||||
if(FSPerfStats::fpsTuningStrategy == 1)
|
if(fpsTuningStrategy == 1)
|
||||||
{
|
{
|
||||||
// 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit.
|
// 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit.
|
||||||
// the other reflection options make comparatively little change and iof this overshoots we'll be stepping back up later
|
// the other reflection options make comparatively little change and iof this overshoots we'll be stepping back up later
|
||||||
if(LLPipeline::RenderReflectionDetail != -2)
|
if(LLPipeline::RenderReflectionDetail != -2)
|
||||||
{
|
{
|
||||||
gSavedSettings.setS32("RenderReflectionDetail", -2);
|
FSPerfStats::tunables.updateReflectionDetail(-2);
|
||||||
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +365,7 @@ namespace FSPerfStats
|
||||||
auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance;
|
auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance;
|
||||||
if(new_dd != drawDistance)
|
if(new_dd != drawDistance)
|
||||||
{
|
{
|
||||||
gSavedSettings.setF32("RenderFarClip", new_dd);
|
FSPerfStats::tunables.updateFarClip( new_dd );
|
||||||
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -404,15 +414,14 @@ namespace FSPerfStats
|
||||||
}
|
}
|
||||||
if( drawDistance < userTargetDrawDistance )
|
if( drawDistance < userTargetDrawDistance )
|
||||||
{
|
{
|
||||||
gSavedSettings.setF32("RenderFarClip", drawDistance + 10.);
|
FSPerfStats::tunables.updateFarClip( drawDistance + 10. );
|
||||||
}
|
}
|
||||||
if( (target_frame_time_raw * 1.5) > tot_frame_time_raw &&
|
if( (target_frame_time_raw * 1.5) > tot_frame_time_raw &&
|
||||||
FSPerfStats::tunedAvatars == 0 &&
|
FSPerfStats::tunedAvatars == 0 &&
|
||||||
drawDistance >= userTargetDrawDistance)
|
drawDistance >= userTargetDrawDistance)
|
||||||
{
|
{
|
||||||
// if everything else is "max" and we have 50% headroom let's knock the water quality up a notch at a time.
|
// if everything else is "max" and we have 50% headroom let's knock the water quality up a notch at a time.
|
||||||
auto water = gSavedSettings.getS32("RenderReflectionDetail");
|
FSPerfStats::tunables.updateReflectionDetail( gSavedSettings.getS32("RenderReflectionDetail") + 1 );
|
||||||
gSavedSettings.setS32("RenderReflectionDetail", water+1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateSettingsFromRenderCostLimit();
|
updateSettingsFromRenderCostLimit();
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ namespace FSPerfStats
|
||||||
extern std::atomic<int64_t> tunedAvatars;
|
extern std::atomic<int64_t> tunedAvatars;
|
||||||
extern U32 targetFPS; // desired FPS
|
extern U32 targetFPS; // desired FPS
|
||||||
extern U64 renderAvatarMaxART_ns;
|
extern U64 renderAvatarMaxART_ns;
|
||||||
extern U32 fpsTuningStrategy;
|
|
||||||
extern U32 lastGlobalPrefChange;
|
extern U32 lastGlobalPrefChange;
|
||||||
extern std::mutex bufferToggleLock;
|
extern std::mutex bufferToggleLock;
|
||||||
extern bool autoTune;
|
extern bool autoTune;
|
||||||
|
|
@ -116,6 +115,28 @@ namespace FSPerfStats
|
||||||
bool isHUD;
|
bool isHUD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Tunables
|
||||||
|
{
|
||||||
|
static constexpr U32 Nothing{0};
|
||||||
|
static constexpr U32 NonImposters{1};
|
||||||
|
static constexpr U32 ReflectionDetail{2};
|
||||||
|
static constexpr U32 FarClip{4};
|
||||||
|
|
||||||
|
U32 tuningFlag{0};
|
||||||
|
U32 nonImposters;
|
||||||
|
S32 reflectionDetail;
|
||||||
|
F32 farClip;
|
||||||
|
|
||||||
|
void updateFarClip(F32 nv){farClip=nv; tuningFlag |= FarClip;};
|
||||||
|
void updateNonImposters(U32 nv){nonImposters=nv; tuningFlag |= NonImposters;};
|
||||||
|
void updateReflectionDetail(S32 nv){reflectionDetail=nv; tuningFlag |= ReflectionDetail;};
|
||||||
|
|
||||||
|
void applyUpdates();
|
||||||
|
void resetChanges(){tuningFlag=Nothing;};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Tunables tunables;
|
||||||
|
|
||||||
class StatsRecorder{
|
class StatsRecorder{
|
||||||
using Queue = moodycamel::BlockingConcurrentQueue<StatsRecord>;
|
using Queue = moodycamel::BlockingConcurrentQueue<StatsRecord>;
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -1644,6 +1644,12 @@ bool LLAppViewer::doFrame()
|
||||||
{
|
{
|
||||||
// <FS:Beq> Perfstats collection Frame boundary
|
// <FS:Beq> Perfstats collection Frame boundary
|
||||||
{
|
{
|
||||||
|
// and now adjust the visuals from previous frame.
|
||||||
|
if(FSPerfStats::autoTune && FSPerfStats::tunables.tuningFlag != FSPerfStats::Tunables::Nothing)
|
||||||
|
{
|
||||||
|
FSPerfStats::tunables.applyUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_FRAME);
|
FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_FRAME);
|
||||||
|
|
||||||
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
|
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
|
||||||
|
|
|
||||||
|
|
@ -1112,11 +1112,7 @@ void handleRenderAvatarMaxARTChanged(const LLSD& newValue)
|
||||||
{
|
{
|
||||||
FSPerfStats::StatsRecorder::updateRenderCostLimitFromSettings();
|
FSPerfStats::StatsRecorder::updateRenderCostLimitFromSettings();
|
||||||
}
|
}
|
||||||
void handleFPSTuningStrategyChanged(const LLSD& newValue)
|
|
||||||
{
|
|
||||||
const auto newval = gSavedSettings.getU32("FSTuningFPSStrategy");
|
|
||||||
FSPerfStats::fpsTuningStrategy = newval;
|
|
||||||
}
|
|
||||||
void handlePerformanceStatsEnabledChanged(const LLSD& newValue)
|
void handlePerformanceStatsEnabledChanged(const LLSD& newValue)
|
||||||
{
|
{
|
||||||
const auto newval = gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled");
|
const auto newval = gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled");
|
||||||
|
|
@ -1383,7 +1379,6 @@ void settings_setup_listeners()
|
||||||
gSavedSettings.getControl("FSTargetFPS")->getSignal()->connect(boost::bind(&handleTargetFPSChanged, _2));
|
gSavedSettings.getControl("FSTargetFPS")->getSignal()->connect(boost::bind(&handleTargetFPSChanged, _2));
|
||||||
gSavedSettings.getControl("FSAutoTuneFPS")->getSignal()->connect(boost::bind(&handleAutoTuneFPSChanged, _2));
|
gSavedSettings.getControl("FSAutoTuneFPS")->getSignal()->connect(boost::bind(&handleAutoTuneFPSChanged, _2));
|
||||||
gSavedSettings.getControl("FSRenderAvatarMaxART")->getSignal()->connect(boost::bind(&handleRenderAvatarMaxARTChanged, _2));
|
gSavedSettings.getControl("FSRenderAvatarMaxART")->getSignal()->connect(boost::bind(&handleRenderAvatarMaxARTChanged, _2));
|
||||||
gSavedSettings.getControl("FSTuningFPSStrategy")->getSignal()->connect(boost::bind(&handleFPSTuningStrategyChanged, _2));
|
|
||||||
gSavedSettings.getControl("FSPerfStatsCaptureEnabled")->getSignal()->connect(boost::bind(&handlePerformanceStatsEnabledChanged, _2));
|
gSavedSettings.getControl("FSPerfStatsCaptureEnabled")->getSignal()->connect(boost::bind(&handlePerformanceStatsEnabledChanged, _2));
|
||||||
// </FS:Beq>
|
// </FS:Beq>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue