Merge pull request #9490 from ameerj/texture-cache-prealloc

texture_cache: Use pre-allocated heap buffer for texture swizzles
This commit is contained in:
bunnei 2022-12-27 00:07:35 -05:00 committed by GitHub
commit c5de54d509
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 22 deletions

View File

@ -39,6 +39,12 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear); sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear);
sampler_descriptor.cubemap_anisotropy.Assign(1); sampler_descriptor.cubemap_anisotropy.Assign(1);
// These values were chosen based on typical peak swizzle data sizes seen in some titles
static constexpr size_t SWIZZLE_DATA_BUFFER_INITIAL_CAPACITY = 8_MiB;
static constexpr size_t UNSWIZZLE_DATA_BUFFER_INITIAL_CAPACITY = 1_MiB;
swizzle_data_buffer.resize_destructive(SWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
unswizzle_data_buffer.resize_destructive(UNSWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
// Make sure the first index is reserved for the null resources // Make sure the first index is reserved for the null resources
// This way the null resource becomes a compile time constant // This way the null resource becomes a compile time constant
void(slot_images.insert(NullImageParams{})); void(slot_images.insert(NullImageParams{}));
@ -90,7 +96,8 @@ void TextureCache<P>::RunGarbageCollector() {
const auto copies = FullDownloadCopies(image.info); const auto copies = FullDownloadCopies(image.info);
image.DownloadMemory(map, copies); image.DownloadMemory(map, copies);
runtime.Finish(); runtime.Finish();
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span); SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span,
swizzle_data_buffer);
} }
if (True(image.flags & ImageFlagBits::Tracked)) { if (True(image.flags & ImageFlagBits::Tracked)) {
UntrackImage(image, image_id); UntrackImage(image, image_id);
@ -461,7 +468,8 @@ void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) {
const auto copies = FullDownloadCopies(image.info); const auto copies = FullDownloadCopies(image.info);
image.DownloadMemory(map, copies); image.DownloadMemory(map, copies);
runtime.Finish(); runtime.Finish();
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span); SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span,
swizzle_data_buffer);
} }
} }
@ -672,7 +680,8 @@ void TextureCache<P>::PopAsyncFlushes() {
for (const ImageId image_id : download_ids) { for (const ImageId image_id : download_ids) {
const ImageBase& image = slot_images[image_id]; const ImageBase& image = slot_images[image_id];
const auto copies = FullDownloadCopies(image.info); const auto copies = FullDownloadCopies(image.info);
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, download_span); SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, download_span,
swizzle_data_buffer);
download_map.offset += image.unswizzled_size_bytes; download_map.offset += image.unswizzled_size_bytes;
download_span = download_span.subspan(image.unswizzled_size_bytes); download_span = download_span.subspan(image.unswizzled_size_bytes);
} }
@ -734,13 +743,21 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging)
gpu_memory->ReadBlockUnsafe(gpu_addr, mapped_span.data(), mapped_span.size_bytes()); gpu_memory->ReadBlockUnsafe(gpu_addr, mapped_span.data(), mapped_span.size_bytes());
const auto uploads = FullUploadSwizzles(image.info); const auto uploads = FullUploadSwizzles(image.info);
runtime.AccelerateImageUpload(image, staging, uploads); runtime.AccelerateImageUpload(image, staging, uploads);
} else if (True(image.flags & ImageFlagBits::Converted)) { return;
std::vector<u8> unswizzled_data(image.unswizzled_size_bytes); }
auto copies = UnswizzleImage(*gpu_memory, gpu_addr, image.info, unswizzled_data); const size_t guest_size_bytes = image.guest_size_bytes;
ConvertImage(unswizzled_data, image.info, mapped_span, copies); swizzle_data_buffer.resize_destructive(guest_size_bytes);
gpu_memory->ReadBlockUnsafe(gpu_addr, swizzle_data_buffer.data(), guest_size_bytes);
if (True(image.flags & ImageFlagBits::Converted)) {
unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes);
auto copies = UnswizzleImage(*gpu_memory, gpu_addr, image.info, swizzle_data_buffer,
unswizzle_data_buffer);
ConvertImage(unswizzle_data_buffer, image.info, mapped_span, copies);
image.UploadMemory(staging, copies); image.UploadMemory(staging, copies);
} else { } else {
const auto copies = UnswizzleImage(*gpu_memory, gpu_addr, image.info, mapped_span); const auto copies =
UnswizzleImage(*gpu_memory, gpu_addr, image.info, swizzle_data_buffer, mapped_span);
image.UploadMemory(staging, copies); image.UploadMemory(staging, copies);
} }
} }
@ -910,7 +927,7 @@ void TextureCache<P>::InvalidateScale(Image& image) {
} }
template <class P> template <class P>
u64 TextureCache<P>::GetScaledImageSizeBytes(ImageBase& image) { u64 TextureCache<P>::GetScaledImageSizeBytes(const ImageBase& image) {
const u64 scale_up = static_cast<u64>(Settings::values.resolution_info.up_scale * const u64 scale_up = static_cast<u64>(Settings::values.resolution_info.up_scale *
Settings::values.resolution_info.up_scale); Settings::values.resolution_info.up_scale);
const u64 down_shift = static_cast<u64>(Settings::values.resolution_info.down_shift + const u64 down_shift = static_cast<u64>(Settings::values.resolution_info.down_shift +

View File

@ -17,6 +17,7 @@
#include "common/literals.h" #include "common/literals.h"
#include "common/lru_cache.h" #include "common/lru_cache.h"
#include "common/polyfill_ranges.h" #include "common/polyfill_ranges.h"
#include "common/scratch_buffer.h"
#include "video_core/compatible_formats.h" #include "video_core/compatible_formats.h"
#include "video_core/control/channel_state_cache.h" #include "video_core/control/channel_state_cache.h"
#include "video_core/delayed_destruction_ring.h" #include "video_core/delayed_destruction_ring.h"
@ -368,7 +369,7 @@ private:
void InvalidateScale(Image& image); void InvalidateScale(Image& image);
bool ScaleUp(Image& image); bool ScaleUp(Image& image);
bool ScaleDown(Image& image); bool ScaleDown(Image& image);
u64 GetScaledImageSizeBytes(ImageBase& image); u64 GetScaledImageSizeBytes(const ImageBase& image);
Runtime& runtime; Runtime& runtime;
@ -417,6 +418,9 @@ private:
std::unordered_map<GPUVAddr, ImageAllocId> image_allocs_table; std::unordered_map<GPUVAddr, ImageAllocId> image_allocs_table;
Common::ScratchBuffer<u8> swizzle_data_buffer;
Common::ScratchBuffer<u8> unswizzle_data_buffer;
u64 modification_tick = 0; u64 modification_tick = 0;
u64 frame_tick = 0; u64 frame_tick = 0;
}; };

View File

@ -505,7 +505,7 @@ void SwizzlePitchLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
const ImageInfo& info, const BufferImageCopy& copy, const ImageInfo& info, const BufferImageCopy& copy,
std::span<const u8> input) { std::span<const u8> input, Common::ScratchBuffer<u8>& tmp_buffer) {
const Extent3D size = info.size; const Extent3D size = info.size;
const LevelInfo level_info = MakeLevelInfo(info); const LevelInfo level_info = MakeLevelInfo(info);
const Extent2D tile_size = DefaultBlockSize(info.format); const Extent2D tile_size = DefaultBlockSize(info.format);
@ -534,8 +534,8 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
tile_size.height, info.tile_width_spacing); tile_size.height, info.tile_width_spacing);
const size_t subresource_size = sizes[level]; const size_t subresource_size = sizes[level];
const auto dst_data = std::make_unique<u8[]>(subresource_size); tmp_buffer.resize_destructive(subresource_size);
const std::span<u8> dst(dst_data.get(), subresource_size); const std::span<u8> dst(tmp_buffer);
for (s32 layer = 0; layer < info.resources.layers; ++layer) { for (s32 layer = 0; layer < info.resources.layers; ++layer) {
const std::span<const u8> src = input.subspan(host_offset); const std::span<const u8> src = input.subspan(host_offset);
@ -765,8 +765,9 @@ bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config
} }
std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
const ImageInfo& info, std::span<u8> output) { const ImageInfo& info, std::span<const u8> input,
const size_t guest_size_bytes = CalculateGuestSizeInBytes(info); std::span<u8> output) {
const size_t guest_size_bytes = input.size_bytes();
const u32 bpp_log2 = BytesPerBlockLog2(info.format); const u32 bpp_log2 = BytesPerBlockLog2(info.format);
const Extent3D size = info.size; const Extent3D size = info.size;
@ -789,10 +790,6 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP
.image_extent = size, .image_extent = size,
}}; }};
} }
const auto input_data = std::make_unique<u8[]>(guest_size_bytes);
gpu_memory.ReadBlockUnsafe(gpu_addr, input_data.get(), guest_size_bytes);
const std::span<const u8> input(input_data.get(), guest_size_bytes);
const LevelInfo level_info = MakeLevelInfo(info); const LevelInfo level_info = MakeLevelInfo(info);
const s32 num_layers = info.resources.layers; const s32 num_layers = info.resources.layers;
const s32 num_levels = info.resources.levels; const s32 num_levels = info.resources.levels;
@ -980,13 +977,14 @@ std::vector<SwizzleParameters> FullUploadSwizzles(const ImageInfo& info) {
} }
void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info, void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info,
std::span<const BufferImageCopy> copies, std::span<const u8> memory) { std::span<const BufferImageCopy> copies, std::span<const u8> memory,
Common::ScratchBuffer<u8>& tmp_buffer) {
const bool is_pitch_linear = info.type == ImageType::Linear; const bool is_pitch_linear = info.type == ImageType::Linear;
for (const BufferImageCopy& copy : copies) { for (const BufferImageCopy& copy : copies) {
if (is_pitch_linear) { if (is_pitch_linear) {
SwizzlePitchLinearImage(gpu_memory, gpu_addr, info, copy, memory); SwizzlePitchLinearImage(gpu_memory, gpu_addr, info, copy, memory);
} else { } else {
SwizzleBlockLinearImage(gpu_memory, gpu_addr, info, copy, memory); SwizzleBlockLinearImage(gpu_memory, gpu_addr, info, copy, memory, tmp_buffer);
} }
} }
} }

View File

@ -7,6 +7,7 @@
#include <span> #include <span>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/scratch_buffer.h"
#include "video_core/surface.h" #include "video_core/surface.h"
#include "video_core/texture_cache/image_base.h" #include "video_core/texture_cache/image_base.h"
@ -59,6 +60,7 @@ struct OverlapResult {
[[nodiscard]] std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, [[nodiscard]] std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory,
GPUVAddr gpu_addr, const ImageInfo& info, GPUVAddr gpu_addr, const ImageInfo& info,
std::span<const u8> input,
std::span<u8> output); std::span<u8> output);
[[nodiscard]] BufferCopy UploadBufferCopy(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, [[nodiscard]] BufferCopy UploadBufferCopy(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
@ -76,7 +78,8 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
[[nodiscard]] std::vector<SwizzleParameters> FullUploadSwizzles(const ImageInfo& info); [[nodiscard]] std::vector<SwizzleParameters> FullUploadSwizzles(const ImageInfo& info);
void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info, void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info,
std::span<const BufferImageCopy> copies, std::span<const u8> memory); std::span<const BufferImageCopy> copies, std::span<const u8> memory,
Common::ScratchBuffer<u8>& tmp_buffer);
[[nodiscard]] bool IsBlockLinearSizeCompatible(const ImageInfo& new_info, [[nodiscard]] bool IsBlockLinearSizeCompatible(const ImageInfo& new_info,
const ImageInfo& overlap_info, u32 new_level, const ImageInfo& overlap_info, u32 new_level,