mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
graphics: preserve full tiled array backing in image-to-buffer copies
This commit is contained in:
+4
-6
@@ -1792,14 +1792,12 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uin
|
||||
const auto available = buffer.Size() - buf_offset;
|
||||
uint32_t levels = 0;
|
||||
uint64_t copy_size = 0;
|
||||
if (image.info.IsVolume()) {
|
||||
// Volume mips contain strided block slices, so a mip's linear span cannot prove that
|
||||
// every retained slice fits. Keep volume synchronization whole-image only.
|
||||
if (!buffer.IsInBounds(image.info.data.address, image.info.data.size)) {
|
||||
return false;
|
||||
}
|
||||
if (buffer.IsInBounds(image.info.data.address, image.info.data.size)) {
|
||||
levels = image.info.resources.levels;
|
||||
copy_size = image.info.data.size;
|
||||
} else if (image.info.IsVolume() || image.info.resources.layers > 1) {
|
||||
// Array and volume slices are strided across the full mip chain.
|
||||
return false;
|
||||
} else {
|
||||
for (; levels < image.info.resources.levels; ++levels) {
|
||||
const auto& mip = image.info.mip_layout[levels];
|
||||
|
||||
@@ -5112,7 +5112,7 @@ public:
|
||||
void CheckUnifiedTextureCacheFlow() {
|
||||
constexpr const char *name = "UnifiedTextureCacheFlow";
|
||||
constexpr uintptr_t base = 0x0000000200600000ull;
|
||||
constexpr uint64_t allocation_size = 0x2c00000;
|
||||
constexpr uint64_t allocation_size = 0x3000000;
|
||||
constexpr uint64_t allocation_alignment = 0x200000;
|
||||
EnsureRuntimeContext();
|
||||
RenderContext context(m_runtime_context);
|
||||
@@ -5670,6 +5670,81 @@ public:
|
||||
"raw render-target copying overwrote the BC5 guest mip layout");
|
||||
DestroyBuffer(&bc5_readback);
|
||||
|
||||
{
|
||||
constexpr uint64_t tiled_array_offset = 0x2c00000;
|
||||
constexpr uint32_t tiled_levels = 5, tiled_layers = 6;
|
||||
TileSurfaceLayout surface{};
|
||||
Require(name, "tiled array alias layout",
|
||||
TileGetTiledTextureLayout(
|
||||
{Prospero::BufferFormat::k32UInt, Prospero::TileMode::kStandard64KB,
|
||||
TileSurfaceDimension::Dim2D, 256, 256, 1, tiled_levels, tiled_layers},
|
||||
surface) && surface.total_size == 0x240000 &&
|
||||
surface.block_slice_size == 0x60000 &&
|
||||
surface.mips[0].offset + surface.mips[0].size * tiled_layers == 0x1a0000,
|
||||
"fixture lost the gap between an array mip span and its full backing");
|
||||
auto tiled_array = MakeLinearDesc(
|
||||
base + tiled_array_offset, surface.total_size, vk::Format::eR32Uint,
|
||||
Prospero::BufferFormat::k32UInt, Prospero::ImageType::kColor2D,
|
||||
{256, 256, 1}, tiled_layers, sizeof(uint32_t), 1);
|
||||
tiled_array.info.tile_mode = Prospero::TileMode::kStandard64KB;
|
||||
tiled_array.info.resources.levels = tiled_levels;
|
||||
tiled_array.view_info.level_count = tiled_levels;
|
||||
for (uint32_t level = 0; level < tiled_levels; ++level) {
|
||||
const auto &mip = surface.mips[level];
|
||||
tiled_array.info.mip_layout[level] = {
|
||||
mip.offset, mip.size * tiled_layers, mip.padded_width, mip.padded_height};
|
||||
}
|
||||
std::memset(memory + tiled_array_offset, 0, surface.total_size);
|
||||
const auto tiled_array_id = texture_cache.FindImage(tiled_array);
|
||||
(void)texture_cache.FindTexture(tiled_array_id, tiled_array);
|
||||
constexpr uint32_t all_mips = 0x12345678u, last_mip = 0x89abcdefu;
|
||||
vk::ClearValue clear{};
|
||||
clear.color.uint32[0] = all_mips;
|
||||
TextureCacheTestAccess::ClearImage(
|
||||
texture_cache, scheduler.Current(), tiled_array_id,
|
||||
{vk::ImageAspectFlagBits::eColor, 0, tiled_levels, 0, tiled_layers}, clear);
|
||||
clear.color.uint32[0] = last_mip;
|
||||
TextureCacheTestAccess::ClearImage(
|
||||
texture_cache, scheduler.Current(), tiled_array_id,
|
||||
{vk::ImageAspectFlagBits::eColor, tiled_levels - 1, 1, tiled_layers - 1, 1}, clear);
|
||||
Libs::Graphics::Buffer full_array(
|
||||
m_runtime_context, scheduler, MemoryUsage::DeviceLocal,
|
||||
tiled_array.info.data.address, AllFlags, surface.total_size);
|
||||
Libs::Graphics::Buffer partial_array(
|
||||
m_runtime_context, scheduler, MemoryUsage::DeviceLocal,
|
||||
tiled_array.info.data.address, AllFlags, 0x1a0000);
|
||||
Require(name, "tiled array alias containment",
|
||||
BufferCacheTestAccess::SynchronizeBufferFromImage(
|
||||
resources.GetBufferCache(), full_array,
|
||||
tiled_array.info.data.address, surface.total_size) &&
|
||||
!BufferCacheTestAccess::SynchronizeBufferFromImage(
|
||||
resources.GetBufferCache(), partial_array,
|
||||
tiled_array.info.data.address, 0x1a0000),
|
||||
"full array synchronization failed or accepted an incomplete slice chain");
|
||||
auto readback = CreateHostBuffer(name, 2 * sizeof(uint32_t),
|
||||
vk::BufferUsageFlagBits::eTransferDst, {0, 0});
|
||||
TransferReadBarrier(full_array.Handle(), surface.total_size);
|
||||
for (uint32_t probe = 0; probe < 2; ++probe) {
|
||||
const auto &mip = surface.mips[probe == 0 ? 0 : tiled_levels - 1];
|
||||
uint32_t within_block = 0;
|
||||
Require(name, "tiled array probe address",
|
||||
TileGetBlockOffset(surface.texture.block, mip.tail_x, mip.tail_y,
|
||||
0, within_block),
|
||||
"last-layer mip origin has no guest address");
|
||||
const vk::BufferCopy copy{
|
||||
(tiled_layers - 1) * surface.block_slice_size + mip.offset + within_block,
|
||||
probe * sizeof(uint32_t), sizeof(uint32_t)};
|
||||
command.Handle().copyBuffer(full_array.Handle(), readback.buffer, 1, ©);
|
||||
}
|
||||
HostReadBarrier(readback.buffer, readback.size, vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::AccessFlagBits::eTransferWrite);
|
||||
scheduler.Finish();
|
||||
Require(name, "tiled array last-layer contents",
|
||||
ReadBuffer(name, readback, 2) == std::vector<u32>{all_mips, last_mip},
|
||||
"array synchronization lost GPU contents beyond the first mip span");
|
||||
DestroyBuffer(&readback);
|
||||
}
|
||||
|
||||
// A formatted Buffer read must use the private
|
||||
// Exercise the cache-native image-copy path. Use a request larger
|
||||
// than the stream shortcut and poison guest backing
|
||||
|
||||
Reference in New Issue
Block a user