mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-18 17:00:50 +02:00
324 lines
14 KiB
C++
324 lines
14 KiB
C++
// Modified by vii from komaruworld/mocktail. See README "About this fork".
|
|
#include "runtime/performance_policy.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#define JSON_NOEXCEPTION 1
|
|
#include <nlohmann/json.hpp>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace mocktail {
|
|
namespace runtime {
|
|
namespace {
|
|
|
|
TEST(PerformancePolicyTest, ParsesDisabledByDefaultAndExplicitTrueValues) {
|
|
EXPECT_FALSE(ParsePerformancePolicy("").multithreaded_rendering);
|
|
EXPECT_FALSE(ParsePerformancePolicy("0").multithreaded_rendering);
|
|
EXPECT_FALSE(ParsePerformancePolicy("false").multithreaded_rendering);
|
|
EXPECT_FALSE(ParsePerformancePolicy("off").multithreaded_rendering);
|
|
EXPECT_TRUE(ParsePerformancePolicy("1").multithreaded_rendering);
|
|
EXPECT_TRUE(ParsePerformancePolicy("true").multithreaded_rendering);
|
|
EXPECT_TRUE(ParsePerformancePolicy("on").multithreaded_rendering);
|
|
EXPECT_EQ(ParsePerformancePolicy("0").physical_core_count, 0);
|
|
EXPECT_GT(ParsePerformancePolicy("true").physical_core_count, 0);
|
|
EXPECT_GT(DetectAvailablePhysicalCoreCount(), 0);
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, ParsesPhysicsWorkerMode) {
|
|
PhysicsWorkerMode mode = PhysicsWorkerMode::kLatency;
|
|
EXPECT_TRUE(ParsePhysicsWorkerMode("auto", &mode));
|
|
EXPECT_EQ(mode, PhysicsWorkerMode::kAuto);
|
|
EXPECT_TRUE(ParsePhysicsWorkerMode("latency", &mode));
|
|
EXPECT_EQ(mode, PhysicsWorkerMode::kLatency);
|
|
EXPECT_TRUE(ParsePhysicsWorkerMode("throughput", &mode));
|
|
EXPECT_EQ(mode, PhysicsWorkerMode::kThroughput);
|
|
EXPECT_FALSE(ParsePhysicsWorkerMode("maximum", &mode));
|
|
EXPECT_FALSE(ParsePhysicsWorkerMode("latency", nullptr));
|
|
EXPECT_EQ(PhysicsWorkerModeName(PhysicsWorkerMode::kAuto), "auto");
|
|
EXPECT_EQ(PhysicsWorkerModeName(PhysicsWorkerMode::kLatency), "latency");
|
|
EXPECT_EQ(PhysicsWorkerModeName(PhysicsWorkerMode::kThroughput),
|
|
"throughput");
|
|
|
|
const PerformancePolicy latency =
|
|
ParsePerformancePolicy("0", "0", "auto", "latency");
|
|
EXPECT_TRUE(latency.physics_worker_mode_valid);
|
|
EXPECT_EQ(latency.physics_worker_mode, PhysicsWorkerMode::kLatency);
|
|
EXPECT_EQ(latency.physical_core_count, 0);
|
|
const PerformancePolicy throughput =
|
|
ParsePerformancePolicy("0", "0", "auto", "throughput");
|
|
EXPECT_TRUE(throughput.physics_worker_mode_valid);
|
|
EXPECT_EQ(throughput.physics_worker_mode, PhysicsWorkerMode::kThroughput);
|
|
EXPECT_GT(throughput.physical_core_count, 0);
|
|
EXPECT_FALSE(ParsePerformancePolicy("0", "0", "auto", "fast")
|
|
.physics_worker_mode_valid);
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, MakesEveryPhysicalCoreAvailableToThroughputMode) {
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(1), 1);
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(2), 2);
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(4), 4);
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(8), 8);
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(14), 14);
|
|
EXPECT_EQ(CalculateThroughputWorkerCount(32), 32);
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, ParsesOptionalMemoryLimitInMebibytes) {
|
|
const PerformancePolicy disabled = ParsePerformancePolicy("0", "0");
|
|
EXPECT_TRUE(disabled.memory_limit_valid);
|
|
EXPECT_FALSE(disabled.memory_limit_enabled());
|
|
EXPECT_EQ(disabled.memory_limit_bytes(), 0U);
|
|
|
|
const PerformancePolicy limited = ParsePerformancePolicy("0", "6144");
|
|
EXPECT_TRUE(limited.memory_limit_valid);
|
|
EXPECT_TRUE(limited.memory_limit_enabled());
|
|
EXPECT_EQ(limited.memory_limit_mb, 6144U);
|
|
EXPECT_EQ(limited.memory_limit_bytes(), 6144ULL * 1024ULL * 1024ULL);
|
|
|
|
EXPECT_FALSE(ParsePerformancePolicy("0", "-1").memory_limit_valid);
|
|
EXPECT_FALSE(ParsePerformancePolicy("0", "6GiB").memory_limit_valid);
|
|
EXPECT_FALSE(ParsePerformancePolicy("0", "").memory_limit_valid);
|
|
EXPECT_FALSE(
|
|
ParsePerformancePolicy("0", "18446744073709551615").memory_limit_valid);
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, DisabledPolicyPreservesUnrelatedOverrides) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
{}, R"({"FStringGraphicsVulkanShaderMTDenyPattern":"4318:.*"})", &merged,
|
|
&error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
ASSERT_TRUE(parsed.is_object());
|
|
EXPECT_EQ(parsed.at("FStringGraphicsVulkanShaderMTDenyPattern"), "4318:.*");
|
|
EXPECT_FALSE(
|
|
parsed.contains("FIntTaskSchedulerAsyncTasksMinimumThreadCount"));
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, SizesFullMultithreadingFromPhysicalCoreCount) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
{true, 14}, R"({"DFIntTaskSchedulerTargetFps":"240"})", &merged, &error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
ASSERT_TRUE(parsed.is_object());
|
|
EXPECT_EQ(parsed.at("DFIntTaskSchedulerTargetFps"), "240");
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerThreadMin"), "14");
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerAsyncTasksMinimumThreadCount"), "14");
|
|
EXPECT_EQ(parsed.at("FIntSmoothClusterTaskQueueMaxParallelTasks"), "14");
|
|
EXPECT_EQ(parsed.at("FIntOcclusionWorkerThreadCount"), "7");
|
|
EXPECT_EQ(parsed.at("FFlagMovePrerenderV2"), "True");
|
|
EXPECT_EQ(parsed.at("FFlagGcInParallelWithRenderPrepare3"), "True");
|
|
EXPECT_FALSE(parsed.contains("FIntTaskSchedulerAutoThreadLimit"));
|
|
EXPECT_FALSE(parsed.contains("FFlagTaskSchedulerLimitTargetFpsTo2402"));
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, AcceptsIdenticalExplicitModeValues) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
{true, 14},
|
|
R"({"FIntOcclusionWorkerThreadCount":"7","FFlagMovePrerenderV2":"True"})",
|
|
&merged, &error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
ASSERT_TRUE(parsed.is_object());
|
|
EXPECT_EQ(parsed.at("FIntOcclusionWorkerThreadCount"), "7");
|
|
EXPECT_EQ(parsed.at("FFlagMovePrerenderV2"), "True");
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, WorkerModesRetainRobloxManagedAssetCacheSizes) {
|
|
for (const bool throughput : {false, true}) {
|
|
PerformancePolicy policy;
|
|
policy.multithreaded_rendering = !throughput;
|
|
policy.physical_core_count = 14;
|
|
policy.physics_worker_mode = throughput ? PhysicsWorkerMode::kThroughput
|
|
: PhysicsWorkerMode::kAuto;
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
policy, "{}", &merged, &error)) << error;
|
|
const auto parsed = nlohmann::json::parse(merged);
|
|
EXPECT_EQ(parsed.at("FIntSmoothClusterTaskQueueMaxParallelTasks"), "14");
|
|
// ForceCacheSize values are bytes, not MiB; tiny fixed values cause
|
|
// immediate eviction instead of preserving the normal asset caches.
|
|
EXPECT_FALSE(parsed.contains("FIntMeshContentProviderForceCacheSize"));
|
|
EXPECT_FALSE(parsed.contains("FIntSlimContentProviderForceCacheSize"));
|
|
}
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, PreservesExplicitAssetCacheByteBudgets) {
|
|
const nlohmann::json requested = {
|
|
{"FIntMeshContentProviderForceCacheSize", "268435456"},
|
|
{"FIntSlimContentProviderForceCacheSize", "134217728"},
|
|
};
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
{true, 14}, requested.dump(), &merged, &error)) << error;
|
|
const auto parsed = nlohmann::json::parse(merged);
|
|
for (const auto& [name, value] : requested.items()) {
|
|
EXPECT_EQ(parsed.at(name), value) << name;
|
|
}
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, LatencyModePreservesRobloxManagedWorkerPools) {
|
|
PerformancePolicy policy =
|
|
ParsePerformancePolicy("true", "0", "auto", "latency");
|
|
policy.physical_core_count = 14;
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(
|
|
MergePerformanceClientSettingsOverrides(policy, "{}", &merged, &error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
ASSERT_TRUE(parsed.is_object());
|
|
EXPECT_EQ(parsed.at("DFIntSimMidPhaseContactPipelineBatchSize"), "128");
|
|
EXPECT_FALSE(parsed.contains("FIntTaskSchedulerThreadMin"));
|
|
EXPECT_FALSE(parsed.contains("FIntTaskSchedulerAutoThreadLimit"));
|
|
EXPECT_FALSE(parsed.contains("FIntSmoothClusterTaskQueueMaxParallelTasks"));
|
|
EXPECT_FALSE(parsed.contains("FIntOcclusionWorkerThreadCount"));
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, ThroughputModeUsesEveryPhysicalCore) {
|
|
PerformancePolicy policy =
|
|
ParsePerformancePolicy("false", "0", "auto", "throughput");
|
|
policy.physical_core_count = 14;
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(
|
|
MergePerformanceClientSettingsOverrides(policy, "{}", &merged, &error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerThreadMin"), "0");
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerAutoThreadLimit"), "14");
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerAsyncTasksMinimumThreadCount"), "3");
|
|
EXPECT_EQ(parsed.at("DFIntSimMidPhaseContactPipelineBatchSize"), "128");
|
|
EXPECT_EQ(parsed.at("FIntSmoothClusterTaskQueueMaxParallelTasks"), "14");
|
|
EXPECT_EQ(parsed.at("FIntOcclusionWorkerThreadCount"), "7");
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, ComposesFrameRateBeforePerformanceMode) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergeRuntimeClientSettingsOverrides(
|
|
ParseFrameRatePolicy("144"), {true, 14},
|
|
R"({"FStringGraphicsVulkanShaderMTDenyPattern":"4318:.*"})", &merged,
|
|
&error))
|
|
<< error;
|
|
|
|
const nlohmann::json parsed =
|
|
nlohmann::json::parse(merged, nullptr, false, true);
|
|
ASSERT_TRUE(parsed.is_object());
|
|
EXPECT_EQ(parsed.at("DFIntTaskSchedulerTargetFps"), "144");
|
|
EXPECT_EQ(parsed.at("FIntTaskSchedulerAsyncTasksMinimumThreadCount"), "14");
|
|
EXPECT_EQ(parsed.at("FStringGraphicsVulkanShaderMTDenyPattern"), "4318:.*");
|
|
EXPECT_EQ(parsed.at("FFlagUseRuntimeMutexRvHttpClient"), "False");
|
|
EXPECT_EQ(parsed.at("DFFlagHttpClientSkipRetryForStreamingRequests"), "True");
|
|
EXPECT_EQ(parsed.at("FFlagLuaAppDefaultHttpRetry"), "False");
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, KeepsUserOverridesThatConflictWithPreset) {
|
|
std::string merged;
|
|
std::string error;
|
|
std::vector<std::string> kept;
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
{true, 14},
|
|
R"({"FIntOcclusionWorkerThreadCount":"2","FFlagMovePrerenderV2":true,)"
|
|
R"("FIntDebugForceMSAASamples":4})",
|
|
&merged, &error, &kept))
|
|
<< error;
|
|
const nlohmann::json parsed = nlohmann::json::parse(merged);
|
|
EXPECT_EQ(parsed.at("FIntOcclusionWorkerThreadCount"), "2");
|
|
EXPECT_EQ(parsed.at("FFlagMovePrerenderV2"), true);
|
|
EXPECT_EQ(parsed.at("FIntDebugForceMSAASamples"), 4);
|
|
EXPECT_EQ(parsed.at("FFlagFastGPULightGrid"), "True");
|
|
EXPECT_EQ(kept, (std::vector<std::string>{"FIntOcclusionWorkerThreadCount",
|
|
"FFlagMovePrerenderV2",
|
|
"FIntDebugForceMSAASamples"}));
|
|
|
|
PerformancePolicy latency =
|
|
ParsePerformancePolicy("true", "0", "auto", "latency");
|
|
latency.physical_core_count = 14;
|
|
kept.clear();
|
|
ASSERT_TRUE(MergePerformanceClientSettingsOverrides(
|
|
latency, R"({"DFIntSimMidPhaseContactPipelineBatchSize":"64"})", &merged,
|
|
&error, &kept))
|
|
<< error;
|
|
EXPECT_EQ(nlohmann::json::parse(merged)
|
|
.at("DFIntSimMidPhaseContactPipelineBatchSize"),
|
|
"64");
|
|
EXPECT_EQ(kept, (std::vector<std::string>{
|
|
"DFIntSimMidPhaseContactPipelineBatchSize"}));
|
|
|
|
kept.clear();
|
|
ASSERT_TRUE(MergeRuntimeClientSettingsOverrides(
|
|
ParseFrameRatePolicy(""), {true, 14},
|
|
R"({"FIntOcclusionWorkerThreadCount":"2"})", &merged, &error, &kept))
|
|
<< error;
|
|
EXPECT_EQ(kept, (std::vector<std::string>{"FIntOcclusionWorkerThreadCount"}));
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, RejectsMalformedOverrides) {
|
|
std::string merged = "unchanged";
|
|
std::string error;
|
|
EXPECT_FALSE(MergePerformanceClientSettingsOverrides({true, 14}, "not-json",
|
|
&merged, &error));
|
|
EXPECT_EQ(merged, "unchanged");
|
|
EXPECT_NE(error.find("JSON object"), std::string::npos);
|
|
|
|
error.clear();
|
|
EXPECT_FALSE(MergePerformanceClientSettingsOverrides({true, 14}, "[]",
|
|
&merged, &error));
|
|
EXPECT_EQ(merged, "unchanged");
|
|
EXPECT_NE(error.find("JSON object"), std::string::npos);
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, HostAudioMenuUsesBridgedDeviceQueries) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergeAudioDeviceMenuClientSettingsOverrides(
|
|
R"({"FFlagDebugUseWebRtcAudioDevices":"True","FFlagRemoteAudioDeviceSync":"True","unrelated":123})",
|
|
&merged, &error));
|
|
const auto parsed = nlohmann::json::parse(merged);
|
|
EXPECT_EQ(parsed.at("FFlagDebugUseWebRtcAudioDevices"), "False");
|
|
EXPECT_EQ(parsed.at("FFlagRemoteAudioDeviceSync"), "False");
|
|
EXPECT_EQ(parsed.at("unrelated"), 123);
|
|
EXPECT_FALSE(parsed.contains("DFFlagVoiceChatSkipPermissionCheckForTests"));
|
|
EXPECT_FALSE(
|
|
MergeAudioDeviceMenuClientSettingsOverrides("[]", &merged, &error));
|
|
}
|
|
|
|
TEST(PerformancePolicyTest, PermissionProtocolDoesNotUseTheTestBypass) {
|
|
std::string merged;
|
|
std::string error;
|
|
ASSERT_TRUE(MergeAudioCaptureClientSettingsOverrides(
|
|
true, R"({"DFFlagVoiceChatSkipPermissionCheckForTests":"True"})", &merged,
|
|
&error))
|
|
<< error;
|
|
nlohmann::json parsed = nlohmann::json::parse(merged);
|
|
EXPECT_EQ(parsed.at("DFFlagVoiceChatSkipPermissionCheckForTests"), "False");
|
|
|
|
ASSERT_TRUE(MergeAudioCaptureClientSettingsOverrides(false, merged, &merged,
|
|
&error))
|
|
<< error;
|
|
parsed = nlohmann::json::parse(merged);
|
|
EXPECT_EQ(parsed.at("DFFlagVoiceChatSkipPermissionCheckForTests"), "False");
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace runtime
|
|
} // namespace mocktail
|