Frame-row capture: only environment-family banks provide the scene rows
This commit is contained in:
parent
60be1f9316
commit
9526ebbf21
1 changed files with 42 additions and 1 deletions
|
|
@ -2253,11 +2253,52 @@ void OnDrawDone(uint8_t* base, uint32_t func, uint32_t r4, uint32_t r5, uint32_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uint32_t ps_bank = g_ps_bank.load(std::memory_order_relaxed);
|
const uint32_t ps_bank = g_ps_bank.load(std::memory_order_relaxed);
|
||||||
|
// POSITIVE family check for the receiver-row capture, by shader debug
|
||||||
|
// path: the value gates below cannot fully discriminate;
|
||||||
|
// flowingwater_defaultPS keeps the ENTIRE baseenvironment receiver
|
||||||
|
// layout (CSM rows, sun c6, camera c7, dim c8) but its material
|
||||||
|
// multiplier c11.y is 0.2, not 1.0. When the canal was in view its
|
||||||
|
// draw won the first-pass race and the whole world tone chain ran at
|
||||||
|
// x0.2 linear, the "world goes dark at some camera rotations" bug
|
||||||
|
// (native exactly 0.50x emulated, uniform). Only the environment
|
||||||
|
// families that share the c10.x/c11.y layout are eligible.
|
||||||
|
const auto env_receiver_ps = [&]() -> bool {
|
||||||
|
const auto check = [&](uint32_t obj) -> int { // 0 unknown, 1 no, 2 yes
|
||||||
|
if (obj < 0x10000 || !GuestReadableApprox(base, obj)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static std::unordered_map<uint32_t, int> cache;
|
||||||
|
auto it = cache.find(obj);
|
||||||
|
if (it != cache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
char text[120] = {};
|
||||||
|
for (int k = 0; k < 119; ++k) {
|
||||||
|
text[k] = char(REX_LOAD_U8(obj + 0x54 + k));
|
||||||
|
if (text[k] == '\0') break;
|
||||||
|
}
|
||||||
|
const bool hit = std::strstr(text, "\\baseenvironment") != nullptr ||
|
||||||
|
std::strstr(text, "\\defaultenvironment") != nullptr ||
|
||||||
|
std::strstr(text, "\\decalenvironment") != nullptr;
|
||||||
|
// Empty/garbled paths stay unknown (0) and are not cached-in as
|
||||||
|
// negatives forever.
|
||||||
|
const int result = text[0] == '\0' ? 0 : (hit ? 2 : 1);
|
||||||
|
if (result != 0 && cache.size() < 4096) {
|
||||||
|
cache.emplace(obj, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const int a = check(g_cur_ps_obj.load(std::memory_order_relaxed));
|
||||||
|
if (a != 0) {
|
||||||
|
return a == 2;
|
||||||
|
}
|
||||||
|
return check(g_cur_vs_obj.load(std::memory_order_relaxed)) == 2;
|
||||||
|
};
|
||||||
// Not gated on the shadows cvar: the captured rows also carry the
|
// Not gated on the shadows cvar: the captured rows also carry the
|
||||||
// scene exposure / material multiplier / sun direction consumed by the
|
// scene exposure / material multiplier / sun direction consumed by the
|
||||||
// exact world shading (rows 40/45/24..26); shading must not die when
|
// exact world shading (rows 40/45/24..26); shading must not die when
|
||||||
// dynamic shadows are toggled off.
|
// dynamic shadows are toggled off.
|
||||||
if (!g_shadow_frame_done && ps_bank != 0) {
|
if (!g_shadow_frame_done && ps_bank != 0 && env_receiver_ps()) {
|
||||||
float rows[48];
|
float rows[48];
|
||||||
for (int i = 0; i < 48; ++i) {
|
for (int i = 0; i < 48; ++i) {
|
||||||
rows[i] = LoadGuestF32(base, ps_bank + i * 4);
|
rows[i] = LoadGuestF32(base, ps_bank + i * 4);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue