Files
Felipe Prado 9ca82cb552 Fix(TextureCache): fixed alias copies with different widths
EN-US

- Fixed synchronization between images sharing an address, pitch
  and layout but having different logical widths
- Limited copies to the common width and height of both images
- Preserved incompatible format and memory layout checks
- Added regression coverage for the captured 1706x960 scene and
  padded integer views with width 1792 and different heights
- Reproduced the failure before the fix and passed six focused
  checks and the renderer build after the change
- Validated water rendering with FSR 3.1 Quality on RX 6700 XT,
  with frame generation disabled
- Confirmed byte-for-byte agreement across the useful image region,
  previously zeroed in the copy consumed by the water pass
- Recorded pending validation with FSR 4, frame generation,
  Linux and NVIDIA hardware
- Recorded the existing scene-resolution-test failure, also
  reproduced on the unchanged baseline

---

PT-BR

- Corrigida sincronização entre imagens com mesmo endereço, passo
  e layout, mas com larguras lógicas diferentes
- Limitadas cópias à largura e altura comuns às duas imagens
- Preservadas verificações de formatos e layouts incompatíveis
- Adicionada regressão para a cena capturada em 1706x960 e suas
  visões inteiras com largura 1792 e diferentes alturas
- Reproduzida falha antes da correção e aprovadas seis verificações
  focadas e a compilação do renderer após a alteração
- Validada renderização da água com FSR 3.1 Quality na RX 6700 XT,
  com geração de quadros desligada
- Confirmada correspondência byte a byte da região útil da imagem,
  anteriormente zerada na cópia consumida pelo passe da água
- Registradas pendências de validação com FSR 4, geração de quadros,
  Linux e hardware NVIDIA
- Registrada falha preexistente do scene-resolution-test, também
  reproduzida na versão original sem alterações
2026-10-27 20:35:27 -03:00

90 lines
3.6 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
// Copy extents between images that share guest memory (texture_cache/aliasing.h); adapted from
// cuesta4/shadPS4 (eltutz) tests/test_aliasing.cpp. No game, Vulkan device or window required.
#include <cassert>
#include <cstdio>
#include "video_core/amdgpu/resource.h"
#include "video_core/texture_cache/aliasing.h"
#include "video_core/texture_cache/image_info.h"
using namespace VideoCore;
static ImageInfo Make(Extent3D size, vk::Format format = vk::Format::eR8G8B8A8Unorm) {
ImageInfo info{};
info.guest_address = 0x100000;
info.num_bits = 32;
info.pixel_format = format;
info.type = AmdGpu::ImageType::Color2D;
info.pitch = size.width;
info.size = size;
return info;
}
int main() {
// Same format: the smaller image is fully covered by the larger one.
{
const ImageInfo src = Make({1920, 1088, 1}), dst = Make({1920, 1080, 1});
assert(GetAliasCopyExtent(src, dst) == dst.size);
assert(GetAliasCopyExtent(dst, src) == dst.size);
}
// Compatible views of other formats: the common rows.
{
const ImageInfo src = Make({1920, 1088, 1}, vk::Format::eR8G8B8A8Uint);
const ImageInfo dst = Make({1920, 1080, 1}, vk::Format::eR8G8B8A8Unorm);
const Extent3D rows{1920, 1080, 1};
assert(GetAliasCopyExtent(src, dst) == rows);
assert(GetAliasCopyExtent(dst, src) == rows);
}
// Captured water copy: the integer view includes row padding, but shares the tiled layout.
{
auto scene = Make({1706, 960, 1}, vk::Format::eR8G8B8A8Srgb);
scene.pitch = 1792;
scene.tile_mode = AmdGpu::TileMode::Display2DThin;
scene.array_mode = AmdGpu::ArrayMode::Array2DTiledThin1;
for (const u32 height : {466u, 576u, 764u, 959u}) {
auto copy = Make({1792, height, 1}, vk::Format::eR8G8B8A8Uint);
copy.tile_mode = scene.tile_mode;
copy.array_mode = scene.array_mode;
const Extent3D common{1706, height, 1};
assert(GetAliasCopyExtent(scene, copy) == common);
assert(GetAliasCopyExtent(copy, scene) == common);
auto incompatible = copy;
incompatible.pitch = 1920;
assert(!GetAliasCopyExtent(scene, incompatible));
incompatible = copy;
incompatible.tile_mode = AmdGpu::TileMode::Display1DThin;
assert(!GetAliasCopyExtent(scene, incompatible));
incompatible = copy;
incompatible.bank_swizzle = scene.bank_swizzle + 1;
assert(!GetAliasCopyExtent(scene, incompatible));
}
}
// Other memory layouts never alias.
{
const ImageInfo src = Make({1920, 1088, 1});
ImageInfo dst = Make({1920, 1080, 1});
dst.guest_address += 0x1000;
assert(!GetAliasCopyExtent(src, dst));
dst = Make({1920, 1080, 1});
++dst.pitch;
assert(!GetAliasCopyExtent(src, dst));
dst = Make({1920, 1080, 1});
dst.props.is_depth = true;
assert(!GetAliasCopyExtent(src, dst));
}
// Incompatible intersections.
{
const ImageInfo src = Make({1920, 1088, 1}, vk::Format::eR8G8B8A8Uint);
ImageInfo dst = Make({1280, 1080, 1}, vk::Format::eR8G8B8A8Unorm);
assert(!GetAliasCopyExtent(src, dst));
dst = Make({1920, 1080, 1}, vk::Format::eR16G16B16A16Sfloat);
assert(!GetAliasCopyExtent(src, dst));
dst = Make({1920, 1080, 1}, vk::Format::eR8G8B8A8Unorm);
dst.resources.levels = 2;
assert(!GetAliasCopyExtent(src, dst));
}
std::puts("aliasing-test: OK");
return 0;
}