mirror of
https://github.com/sal063/AC6_recomp
synced 2026-08-22 23:21:35 -04:00
Fix AC6 >1x mosaic and cloud/effects de-swizzle streaks
Upscale mosaic. At draw-resolution scale > 1, AC6's deferred EDRAM restore passes do integer pixel-address math on the PsParamGen position. Its leftover sub-guest-pixel fraction scrambles into an 8x8 mosaic. Floor the param-gen position (param_gen_integer_guest_position) and re-add the host sub-pixel at the fetch (param_gen_host_subpixel_restore). Inert at 1x. De-swizzle scramble. Some AC6 restore/resample passes manually de-swizzle the Xenos EDRAM sub-tile layout of their source, which is only correct on tiled data. The emulator detiles everything to linear, so the de-swizzle always scrambles, streaking the cloud/effects pipeline. For allowlisted shader hashes (ac6_neutralize_deswizzle_hashes) the sample coordinate is replaced with the identity host-texel UV (a 1:1 copy).
This commit is contained in:
@@ -17,6 +17,9 @@ REXCVAR_DECLARE(bool, direct_host_resolve);
|
||||
REXCVAR_DECLARE(int32_t, resolution_scale);
|
||||
REXCVAR_DECLARE(int32_t, draw_resolution_scale_x);
|
||||
REXCVAR_DECLARE(int32_t, draw_resolution_scale_y);
|
||||
REXCVAR_DECLARE(bool, param_gen_integer_guest_position);
|
||||
REXCVAR_DECLARE(bool, param_gen_host_subpixel_restore);
|
||||
REXCVAR_DECLARE(std::string, ac6_neutralize_deswizzle_hashes);
|
||||
REXCVAR_DECLARE(std::string, log_file);
|
||||
REXCVAR_DECLARE(std::string, log_level);
|
||||
REXCVAR_DECLARE(bool, ac6_d3d_trace);
|
||||
@@ -54,6 +57,19 @@ REXCVAR_DEFINE_STRING(ac6_graphics_backend, AC6_DEFAULT_GRAPHICS_BACKEND,
|
||||
REXCVAR_DEFINE_BOOL(ac6_performance_mode, true, "AC6/Performance",
|
||||
"Disable all diagnostics, logging, and development overlays for maximum runtime performance");
|
||||
|
||||
// Correctness-fix switches. Each expands
|
||||
// to its detailed cvars + AC6-specific shader hashes in ApplyAc6FixDefaults()
|
||||
// unless the user overrode them.
|
||||
REXCVAR_DEFINE_BOOL(ac6_fix_scaling, true, "AC6",
|
||||
"Fix the upscaling mosaic on AC6's deferred EDRAM restore passes by "
|
||||
"flooring the PsParamGen pixel position (+ host sub-pixel restore). "
|
||||
"Auto-applies only at draw resolution scale > 1; inert at 1x. On by default.");
|
||||
REXCVAR_DEFINE_BOOL(ac6_fix_deswizzle, true, "AC6",
|
||||
"Fix the de-swizzle mosaic/streaks: identity-override AC6's manual EDRAM "
|
||||
"sub-tile de-swizzle, which is always a wrong texel permutation once the "
|
||||
"emulator detiles to linear. On by default; effective at all draw scales "
|
||||
"(the swizzle is present at 1x too).");
|
||||
|
||||
#include "generated/ac6recomp_config.h"
|
||||
#include "generated/ac6recomp_init.h"
|
||||
|
||||
@@ -82,6 +98,8 @@ void ApplyAc6HybridStartupSafetyOverrides() {
|
||||
REXCVAR_SET(draw_resolution_scale_x, 1);
|
||||
REXCVAR_SET(draw_resolution_scale_y, 1);
|
||||
}
|
||||
// (The >1x param-gen mosaic fix is applied by ApplyAc6FixDefaults via
|
||||
// ac6_fix_scaling.)
|
||||
|
||||
if (REXCVAR_GET(ac6_force_safe_direct_host_resolve)) {
|
||||
REXCVAR_SET(direct_host_resolve, false);
|
||||
@@ -139,6 +157,32 @@ void ApplyAc6PerformanceModeOverrides() {
|
||||
REXCVAR_SET(ac6_texture_swaps_dump_enabled, false);
|
||||
}
|
||||
|
||||
// Each fix switch -> its detailed cvars + AC6-specific shader hashes. The
|
||||
// game-specific constants live here in code, not in the user's toml; each
|
||||
// value is filled in only if the user did NOT set it explicitly, so any toml
|
||||
// override still wins (the dev/debug path).
|
||||
#define AC6_SET_IF_UNSET(cv, value) \
|
||||
do { if (!rex::cvar::HasNonDefaultValue(#cv)) REXCVAR_SET(cv, value); } while (0)
|
||||
|
||||
void ApplyAc6FixDefaults() {
|
||||
const bool scaled = REXCVAR_GET(draw_resolution_scale_x) > 1 ||
|
||||
REXCVAR_GET(draw_resolution_scale_y) > 1;
|
||||
|
||||
// param_gen floor + host sub-pixel restore only bites at >1x --
|
||||
// inert at 1x, so gate it on the draw scale.
|
||||
if (REXCVAR_GET(ac6_fix_scaling) && scaled) {
|
||||
AC6_SET_IF_UNSET(param_gen_integer_guest_position, true);
|
||||
AC6_SET_IF_UNSET(param_gen_host_subpixel_restore, true);
|
||||
}
|
||||
// de-swizzle identity override is a texture-layout mismatch present
|
||||
// at ALL draw scales, so it is NOT gated on scale.
|
||||
if (REXCVAR_GET(ac6_fix_deswizzle)) {
|
||||
AC6_SET_IF_UNSET(ac6_neutralize_deswizzle_hashes,
|
||||
"7d22894002d16018, 17e5e4ac3e713245:4");
|
||||
}
|
||||
}
|
||||
#undef AC6_SET_IF_UNSET
|
||||
|
||||
} // namespace
|
||||
|
||||
void ApplyAc6PerformanceModeOverridesPublic() {
|
||||
@@ -169,6 +213,7 @@ std::unique_ptr<rex::ui::WindowedApp> Ac6recompAppCreate(rex::ui::WindowedAppCon
|
||||
REXCVAR_SET(ac6_unlock_fps, false);
|
||||
ApplyAc6DefaultSettings();
|
||||
ApplyAc6HybridStartupSafetyOverrides();
|
||||
ApplyAc6FixDefaults();
|
||||
ApplyAc6PerformanceModeOverrides();
|
||||
|
||||
REXLOG_INFO("Ac6recompAppCreate: graphics mode={} capture={}",
|
||||
|
||||
Reference in New Issue
Block a user