From f2ee98fe311977b6417d97c82cc6a932f5f0b9b0 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 2 Aug 2026 15:56:24 +0200 Subject: [PATCH] renderer: separate tiled and linear texture capacities --- .../host_gpu/renderer/cache/textureCache.cpp | 17 +++++-- .../host_gpu/renderer/image/textureCommon.cpp | 14 +++--- .../host_gpu/renderer/image/textureCommon.h | 2 +- tests/ShaderRecompilerComputeTests.cpp | 48 +++++++++++++++---- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index 834d242f1..3f4c161ff 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -838,11 +838,20 @@ struct TextureCache::ColorTransferPlan { TextureUploadLayout layout; std::vector regions; std::vector tiles; + uint64_t linear_size = 0; bool tiled = false; bool swap_bgra16 = false; bool valid = false; }; +static uint64_t GetLinearSize(std::span tiles) { + uint64_t size = 0; + for (const auto& tile: tiles) { + size = std::max(size, tile.linear_offset + tile.linear_size); + } + return size; +} + struct TextureCache::DownloadPlan { ColorTransferPlan color; bool depth = false; @@ -919,6 +928,7 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding, info.resources.levels, plan.tiles)) { return plan; } + plan.linear_size = GetLinearSize(plan.tiles); } plan.valid = true; return plan; @@ -967,8 +977,8 @@ void TextureCache::UploadImage(Image& image, const ImageDesc& desc, Buffer& sour } TileManager::Result linear {source.Handle(), source_offset, info.data.size}; if (plan.tiled) { - linear = m_tiler->Detile(source.Handle(), source_offset, info.data.size, info.data.size, - plan.tiles); + linear = m_tiler->Detile(source.Handle(), source_offset, info.data.size, + plan.linear_size, plan.tiles); } if (plan.swap_bgra16) { linear = m_tiler->SwapBgra16(linear); @@ -1574,7 +1584,7 @@ void TextureCache::DownloadImageData(Image& image, Buffer& destination, uint64_t } m_tiler->TileImage(image, color.regions, destination.Handle(), destination_offset, - destination_size, destination_size, color.tiles, transform); + destination_size, color.linear_size, color.tiles, transform); } bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uint64_t size) { @@ -1667,6 +1677,7 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uin image.info.TransferLayers(), levels, color.tiles)) { return false; } + color.linear_size = GetLinearSize(color.tiles); } } m_texture_cache.DownloadImageData(image, buffer, buf_offset, copy_size, std::move(plan)); diff --git a/src/graphics/host_gpu/renderer/image/textureCommon.cpp b/src/graphics/host_gpu/renderer/image/textureCommon.cpp index 0ca19325e..87aec22b0 100644 --- a/src/graphics/host_gpu/renderer/image/textureCommon.cpp +++ b/src/graphics/host_gpu/renderer/image/textureCommon.cpp @@ -482,10 +482,10 @@ static bool SetGpuTileSize(uint64_t offset, uint64_t length, uint64_t capacity, return true; } -bool TextureBuildGpuTileInfos(uint64_t size, const std::vector& regions, +bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector& regions, const TextureUploadLayout& layout, uint32_t fmt, uint32_t depth, uint64_t levels, std::vector& out_infos) { - if (size == 0 || levels == 0 || levels > 16 || depth == 0 || + if (tiled_size == 0 || levels == 0 || levels > 16 || depth == 0 || regions.size() != GetTextureRegionCount(depth, levels, layout.volume_texture) || Prospero::IsFmaskTextureFormat(fmt)) { return false; @@ -538,8 +538,9 @@ bool TextureBuildGpuTileInfos(uint64_t size, const std::vector(copy_depth - 1u) * linear_stride + layout.level_sizes[level].size; - if (!SetGpuTileSize(info.linear_offset, linear_span, size, info.linear_size) || - !SetGpuTileSize(info.tiled_offset, volume.level_sizes[level], size, + if (!SetGpuTileSize(info.linear_offset, linear_span, UINT64_MAX, + info.linear_size) || + !SetGpuTileSize(info.tiled_offset, volume.level_sizes[level], tiled_size, info.tiled_size)) { return false; } @@ -588,8 +589,9 @@ bool TextureBuildGpuTileInfos(uint64_t size, const std::vector TextureBuildImageCopies(const TextureUploadLayo uint32_t width, uint32_t height, uint32_t depth, uint64_t levels, bool array_texture, bool volume_texture); -bool TextureBuildGpuTileInfos(uint64_t size, const std::vector& regions, +bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector& regions, const TextureUploadLayout& layout, uint32_t fmt, uint32_t depth, uint64_t levels, std::vector& infos); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 58046bc3c..52c51124e 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -7279,26 +7279,30 @@ public: } u32 case_index = 0; - auto check_round_trip = [&](const char* stage, uint64_t size, + auto check_round_trip = [&](const char* stage, uint64_t tiled_size, std::span infos) { - std::vector tiled(size); - std::vector cpu(size, 0); - std::vector gpu(size, 0xab); + uint64_t linear_size = 0; + for (const auto& info: infos) { + linear_size = std::max(linear_size, info.linear_offset + info.linear_size); + } + std::vector tiled(tiled_size); + std::vector cpu(linear_size, 0); + std::vector gpu(linear_size, 0xab); fill(&tiled, ++case_index); for (const auto& info: infos) { convert_reference(false, &cpu, tiled, info); } - gpu_detile(tiled, &gpu, size, size, infos); + gpu_detile(tiled, &gpu, tiled_size, linear_size, infos); compare((std::string(stage) + " detile bytes").c_str(), cpu, gpu); - std::vector linear(size); - std::vector cpu_tiled(size, 0xab); - std::vector gpu_tiled(size, 0xab); + std::vector linear(linear_size); + std::vector cpu_tiled(tiled_size, 0xab); + std::vector gpu_tiled(tiled_size, 0xab); fill(&linear, 0x280u + case_index); for (const auto& info: infos) { convert_reference(true, &cpu_tiled, linear, info); } - gpu_tile(linear, &gpu_tiled, size, size, infos); + gpu_tile(linear, &gpu_tiled, tiled_size, linear_size, infos); compare((std::string(stage) + " tile bytes").c_str(), cpu_tiled, gpu_tiled); }; for (const auto family: families) { @@ -7436,6 +7440,32 @@ public: Require(name, "format coverage", format_cases != 0, "no CPU-supported standard formats were tested"); + { + constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::kBc1UNorm); + constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB); + constexpr u32 width = 256, height = 256, levels = 9; + const u32 pitch = TileGetTexturePitch(format, width, levels, tile); + TileSizeAlign total {}; + TileGetTextureSize(format, width, height, pitch, levels, tile, &total, nullptr, + nullptr); + const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, pitch, + tile, total.size, false, false, name); + const auto regions = + TextureBuildImageCopies(layout, width, height, 1, levels, false, false); + std::vector infos; + const bool built = + TextureBuildGpuTileInfos(total.size, regions, layout, format, 1, levels, infos); + uint64_t linear_size = 0; + for (const auto& info: infos) { + linear_size = std::max(linear_size, info.linear_offset + info.linear_size); + } + Require(name, "BC1 mip-tail capacities", + built && total.size == 0x10000 && layout.first_tail_level == 0 && + linear_size == 0x15560 && linear_size > total.size, + "BC1 mip tail conflated tiled and linear capacities"); + check_round_trip("BC1 mip tail", total.size, infos); + } + { constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float); constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);