mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-09-09 18:46:22 -05:00
Latte: mirror small 1D-tiled render targets back to guest memory
Titles that reduce a frame down to a tiny surface on the GPU and then read the result back on the CPU never received that data, because enableReadback was only set for TM_LINEAR_ALIGNED surfaces. Disney Infinity does this for auto exposure. It reduces the frame through 1152x600 -> 284x150 -> 96x48 -> 17x16 -> 4x8 -> a final 1x8 R32_FLOAT holding average scene luminance, then reads that value on the CPU to derive an exposure scalar which it uploads as a shader uniform. The chain is TM_1D_TILED_THIN1, so it was never mirrored back, the game read stale zeros and uploaded an exposure of 0, and the lighting shader (which ends in colour * uf_remappedPS[13].x) rendered the entire scene black. UI is drawn after that multiply and stayed visible, so the symptom was a black scene with working audio, menus and HUD on both the Vulkan and OpenGL backends. Also enable readback for TM_1D_TILED_THIN1 surfaces of at most 64x64. Full size render targets are unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1312,6 +1312,15 @@ LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddre
|
||||
{
|
||||
this->enableReadback = true;
|
||||
}
|
||||
else if (this->tileMode == Latte::E_HWTILEMODE::TM_1D_TILED_THIN1 && (width * height) <= 64 * 64)
|
||||
{
|
||||
// Some titles reduce a frame down to a tiny surface on the GPU and then read the result
|
||||
// back on the CPU - Disney Infinity does this for auto exposure, ending in a 1x8 R32_FLOAT
|
||||
// holding average scene luminance. Those surfaces are 1D tiled rather than linear, so they
|
||||
// would never be mirrored back and the title reads stale memory, computes an exposure of
|
||||
// zero and renders the whole scene black. They are small enough that mirroring them is cheap.
|
||||
this->enableReadback = true;
|
||||
}
|
||||
|
||||
// calculate number of potential mip levels (from effective size)
|
||||
sint32 effectiveWidth = width;
|
||||
|
||||
Reference in New Issue
Block a user