mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Fix] (Pipe): re-arm the verify comparator when any of its three knobs changes, not only when PipeVerify does
- ArmVerify latched PipeVerifyFatal and PipeVerifyCorrupt at the moment PipeVerify changed; a later change to either without a PipeVerify toggle was not seen, so 878db2c4's "re-parse when their value changes" held for one knob of three. - The latch now keys on all three Features values. A lane loads Features before its first fill, so it still arms once per process; cost is two Bool compares and one String compare per fill, verify builds only.
This commit is contained in:
@@ -351,6 +351,7 @@ namespace MobileGL::MG_Pipe {
|
|||||||
Bool Fatal = true;
|
Bool Fatal = true;
|
||||||
Bool InHook = false; // a re-read that re-enters an accessor is not re-verified
|
Bool InHook = false; // a re-read that re-enters an accessor is not re-verified
|
||||||
Optional<MGPipeInputField> Corrupt;
|
Optional<MGPipeInputField> Corrupt;
|
||||||
|
String CorruptKnob; // the MOBILEGL_PIPE_VERIFY_CORRUPT value the last arm saw
|
||||||
std::atomic<Uint64> Divergences{0};
|
std::atomic<Uint64> Divergences{0};
|
||||||
~VerifyState() {
|
~VerifyState() {
|
||||||
const Uint64 count = Divergences.load(std::memory_order_relaxed);
|
const Uint64 count = Divergences.load(std::memory_order_relaxed);
|
||||||
@@ -362,17 +363,24 @@ namespace MobileGL::MG_Pipe {
|
|||||||
};
|
};
|
||||||
VerifyState g_verify;
|
VerifyState g_verify;
|
||||||
|
|
||||||
// Armed on the first fill and re-armed only when Features.PipeVerify changes (the
|
// Armed on the first fill and re-armed when any of the three verify knobs'
|
||||||
// same reason as ParsePoisonOmissionKnob: one arm per lane process, a fresh arm for a
|
// Features value (PipeVerify, PipeVerifyFatal, PipeVerifyCorrupt) differs from what
|
||||||
// forked test child that turns the knob on after its parent filled unarmed).
|
// the last arm latched (the same reason as ParsePoisonOmissionKnob: one arm per lane
|
||||||
|
// process, a fresh arm for a forked test child that turns a knob after its parent
|
||||||
|
// filled). Cost: two Bool compares and one String compare per fill, verify builds only.
|
||||||
void ArmVerify() {
|
void ArmVerify() {
|
||||||
if (g_verify.Parsed && g_verify.Enabled == MG_Config::Features.PipeVerify) return;
|
const auto& features = MG_Config::Features;
|
||||||
|
if (g_verify.Parsed && g_verify.Enabled == features.PipeVerify && g_verify.Fatal == features.PipeVerifyFatal &&
|
||||||
|
g_verify.CorruptKnob == features.PipeVerifyCorrupt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_verify.Parsed = true;
|
g_verify.Parsed = true;
|
||||||
g_verify.Enabled = MG_Config::Features.PipeVerify;
|
g_verify.Enabled = features.PipeVerify;
|
||||||
|
g_verify.Fatal = features.PipeVerifyFatal;
|
||||||
|
g_verify.CorruptKnob = features.PipeVerifyCorrupt;
|
||||||
g_verify.Corrupt = Optional<MGPipeInputField>{};
|
g_verify.Corrupt = Optional<MGPipeInputField>{};
|
||||||
if (!g_verify.Enabled) return;
|
if (!g_verify.Enabled) return;
|
||||||
g_verify.Fatal = MG_Config::Features.PipeVerifyFatal;
|
const String& corrupt = g_verify.CorruptKnob;
|
||||||
const String& corrupt = MG_Config::Features.PipeVerifyCorrupt;
|
|
||||||
if (!corrupt.empty()) {
|
if (!corrupt.empty()) {
|
||||||
const auto field = MGPipeFindInputField(corrupt.c_str());
|
const auto field = MGPipeFindInputField(corrupt.c_str());
|
||||||
if (!field) {
|
if (!field) {
|
||||||
|
|||||||
Reference in New Issue
Block a user