// SPDX-License-Identifier: MIT // Copyright (c) 2026 The Roofer Dev - Beast Roofer Edition. Clean-room integration code. // Built on Ryujinx (MIT). using System; using System.Globalization; namespace Ryujinx.Graphics.Shader.Translation { /// /// [HASH_TEST] Temporary VALIDATION experiment (RYUJINX_HASH_CONST=<float>), inert unless set. /// It answers one question and is meant to be deleted afterwards: is the per-pixel dither hash /// of the XC2 DoF bokeh shader required for the border-streak artifact? /// /// That shader (guest FS 0x1000AE430) computes hash = fract(sin(...) * 43758.5469). While this /// flag is set, the translator replaces ONLY that one multiply's result with the constant, so /// hash = fract(const) and every other part of the shader (CoC, gathers, weights, accumulation, /// normalization, sprite generation) is untouched. See InstEmit.Fmul32i for the injection site. /// /// This is a codegen probe: it alters generated host code, so it MUST be listed in /// DiskCacheHostStorage's probe interlock, otherwise the instrumented shader would be persisted /// and served to a later probe-less launch. It is also address-gated, and the disk-cache /// recompile path passes address 0 (ParallelDiskCacheLoader), so the experiment only actually /// runs with the shader cache disabled -- the [HASH_TEST] log line is the proof it did. /// public static class HashTestProbe { public static readonly float? ConstValue = Parse(); public static bool Enabled => ConstValue.HasValue; private static float? Parse() { string raw = Environment.GetEnvironmentVariable("RYUJINX_HASH_CONST"); // Invariant culture on purpose: "0.5" parses, "0,5" does not and leaves the probe off. if (raw != null && float.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out float value)) { return value; } return null; } } }