From c448b3af2ffe06f036e06b610c87db8dab74b766 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Thu, 22 Dec 2022 16:52:53 -0500
Subject: [PATCH 1/3] texture_cache: Use pre-allocated buffer for texture
uploads
---
src/video_core/texture_cache/texture_cache.h | 26 ++++++++++++++-----
.../texture_cache/texture_cache_base.h | 5 +++-
src/video_core/texture_cache/util.cpp | 9 +++----
src/video_core/texture_cache/util.h | 1 +
4 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 8e68a2e53..fccf4316d 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -39,6 +39,12 @@ TextureCache
::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear);
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.reserve(SWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
+ unswizzle_data_buffer.reserve(UNSWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
+
// Make sure the first index is reserved for the null resources
// This way the null resource becomes a compile time constant
void(slot_images.insert(NullImageParams{}));
@@ -734,13 +740,21 @@ void TextureCache
::UploadImageContents(Image& image, StagingBuffer& staging)
gpu_memory->ReadBlockUnsafe(gpu_addr, mapped_span.data(), mapped_span.size_bytes());
const auto uploads = FullUploadSwizzles(image.info);
runtime.AccelerateImageUpload(image, staging, uploads);
- } else if (True(image.flags & ImageFlagBits::Converted)) {
- std::vector unswizzled_data(image.unswizzled_size_bytes);
- auto copies = UnswizzleImage(*gpu_memory, gpu_addr, image.info, unswizzled_data);
- ConvertImage(unswizzled_data, image.info, mapped_span, copies);
+ return;
+ }
+ const size_t guest_size_bytes = image.guest_size_bytes;
+ swizzle_data_buffer.resize(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(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);
} 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);
}
}
@@ -910,7 +924,7 @@ void TextureCache::InvalidateScale(Image& image) {
}
template
-u64 TextureCache::GetScaledImageSizeBytes(ImageBase& image) {
+u64 TextureCache
::GetScaledImageSizeBytes(const ImageBase& image) {
const u64 scale_up = static_cast(Settings::values.resolution_info.up_scale *
Settings::values.resolution_info.up_scale);
const u64 down_shift = static_cast(Settings::values.resolution_info.down_shift +
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 587339a31..67e8acf25 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -368,7 +368,7 @@ private:
void InvalidateScale(Image& image);
bool ScaleUp(Image& image);
bool ScaleDown(Image& image);
- u64 GetScaledImageSizeBytes(ImageBase& image);
+ u64 GetScaledImageSizeBytes(const ImageBase& image);
Runtime& runtime;
@@ -417,6 +417,9 @@ private:
std::unordered_map image_allocs_table;
+ std::vector swizzle_data_buffer;
+ std::vector unswizzle_data_buffer;
+
u64 modification_tick = 0;
u64 frame_tick = 0;
};
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index e8c908b42..4488fa9da 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -765,8 +765,9 @@ bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config
}
std::vector UnswizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
- const ImageInfo& info, std::span output) {
- const size_t guest_size_bytes = CalculateGuestSizeInBytes(info);
+ const ImageInfo& info, std::span input,
+ std::span output) {
+ const size_t guest_size_bytes = input.size_bytes();
const u32 bpp_log2 = BytesPerBlockLog2(info.format);
const Extent3D size = info.size;
@@ -789,10 +790,6 @@ std::vector UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP
.image_extent = size,
}};
}
- const auto input_data = std::make_unique(guest_size_bytes);
- gpu_memory.ReadBlockUnsafe(gpu_addr, input_data.get(), guest_size_bytes);
- const std::span input(input_data.get(), guest_size_bytes);
-
const LevelInfo level_info = MakeLevelInfo(info);
const s32 num_layers = info.resources.layers;
const s32 num_levels = info.resources.levels;
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index 5e28f4ab3..ddf0b3b06 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -59,6 +59,7 @@ struct OverlapResult {
[[nodiscard]] std::vector UnswizzleImage(Tegra::MemoryManager& gpu_memory,
GPUVAddr gpu_addr, const ImageInfo& info,
+ std::span input,
std::span output);
[[nodiscard]] BufferCopy UploadBufferCopy(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
From 1209d428f14ffc6f1c8b6049b0431c30b26138d6 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Thu, 22 Dec 2022 17:01:39 -0500
Subject: [PATCH 2/3] texture_cache: Use pre-allocated buffer for texture
downloads
---
src/video_core/texture_cache/texture_cache.h | 9 ++++++---
src/video_core/texture_cache/util.cpp | 11 ++++++-----
src/video_core/texture_cache/util.h | 3 ++-
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index fccf4316d..6d7d8226f 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -96,7 +96,8 @@ void TextureCache::RunGarbageCollector() {
const auto copies = FullDownloadCopies(image.info);
image.DownloadMemory(map, copies);
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)) {
UntrackImage(image, image_id);
@@ -467,7 +468,8 @@ void TextureCache
::DownloadMemory(VAddr cpu_addr, size_t size) {
const auto copies = FullDownloadCopies(image.info);
image.DownloadMemory(map, copies);
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);
}
}
@@ -678,7 +680,8 @@ void TextureCache
::PopAsyncFlushes() {
for (const ImageId image_id : download_ids) {
const ImageBase& image = slot_images[image_id];
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_span = download_span.subspan(image.unswizzled_size_bytes);
}
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 4488fa9da..7999a7f06 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -505,7 +505,7 @@ void SwizzlePitchLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
const ImageInfo& info, const BufferImageCopy& copy,
- std::span input) {
+ std::span input, std::vector& tmp_buffer) {
const Extent3D size = info.size;
const LevelInfo level_info = MakeLevelInfo(info);
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);
const size_t subresource_size = sizes[level];
- const auto dst_data = std::make_unique(subresource_size);
- const std::span dst(dst_data.get(), subresource_size);
+ tmp_buffer.resize(subresource_size);
+ const std::span dst(tmp_buffer);
for (s32 layer = 0; layer < info.resources.layers; ++layer) {
const std::span src = input.subspan(host_offset);
@@ -977,13 +977,14 @@ std::vector FullUploadSwizzles(const ImageInfo& info) {
}
void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info,
- std::span copies, std::span memory) {
+ std::span copies, std::span memory,
+ std::vector& tmp_buffer) {
const bool is_pitch_linear = info.type == ImageType::Linear;
for (const BufferImageCopy& copy : copies) {
if (is_pitch_linear) {
SwizzlePitchLinearImage(gpu_memory, gpu_addr, info, copy, memory);
} else {
- SwizzleBlockLinearImage(gpu_memory, gpu_addr, info, copy, memory);
+ SwizzleBlockLinearImage(gpu_memory, gpu_addr, info, copy, memory, tmp_buffer);
}
}
}
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index ddf0b3b06..2c991b4d2 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -77,7 +77,8 @@ void ConvertImage(std::span input, const ImageInfo& info, std::span FullUploadSwizzles(const ImageInfo& info);
void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info,
- std::span copies, std::span memory);
+ std::span copies, std::span memory,
+ std::vector& tmp_buffer);
[[nodiscard]] bool IsBlockLinearSizeCompatible(const ImageInfo& new_info,
const ImageInfo& overlap_info, u32 new_level,
From 7584d36922669808b7c8a62667380453687b0ad9 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 25 Dec 2022 15:47:41 -0500
Subject: [PATCH 3/3] texture_cache: Use Common::ScratchBuffer for swizzle
buffers
---
src/video_core/texture_cache/texture_cache.h | 8 ++++----
src/video_core/texture_cache/texture_cache_base.h | 5 +++--
src/video_core/texture_cache/util.cpp | 6 +++---
src/video_core/texture_cache/util.h | 3 ++-
4 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 6d7d8226f..27c82cd20 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -42,8 +42,8 @@ TextureCache::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
// 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.reserve(SWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
- unswizzle_data_buffer.reserve(UNSWIZZLE_DATA_BUFFER_INITIAL_CAPACITY);
+ 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
// This way the null resource becomes a compile time constant
@@ -746,11 +746,11 @@ void TextureCache
::UploadImageContents(Image& image, StagingBuffer& staging)
return;
}
const size_t guest_size_bytes = image.guest_size_bytes;
- swizzle_data_buffer.resize(guest_size_bytes);
+ 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(image.unswizzled_size_bytes);
+ 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);
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 67e8acf25..4fd677a80 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -17,6 +17,7 @@
#include "common/literals.h"
#include "common/lru_cache.h"
#include "common/polyfill_ranges.h"
+#include "common/scratch_buffer.h"
#include "video_core/compatible_formats.h"
#include "video_core/control/channel_state_cache.h"
#include "video_core/delayed_destruction_ring.h"
@@ -417,8 +418,8 @@ private:
std::unordered_map image_allocs_table;
- std::vector swizzle_data_buffer;
- std::vector unswizzle_data_buffer;
+ Common::ScratchBuffer swizzle_data_buffer;
+ Common::ScratchBuffer unswizzle_data_buffer;
u64 modification_tick = 0;
u64 frame_tick = 0;
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 7999a7f06..03acc68d9 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -505,7 +505,7 @@ void SwizzlePitchLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
const ImageInfo& info, const BufferImageCopy& copy,
- std::span input, std::vector& tmp_buffer) {
+ std::span input, Common::ScratchBuffer& tmp_buffer) {
const Extent3D size = info.size;
const LevelInfo level_info = MakeLevelInfo(info);
const Extent2D tile_size = DefaultBlockSize(info.format);
@@ -534,7 +534,7 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
tile_size.height, info.tile_width_spacing);
const size_t subresource_size = sizes[level];
- tmp_buffer.resize(subresource_size);
+ tmp_buffer.resize_destructive(subresource_size);
const std::span dst(tmp_buffer);
for (s32 layer = 0; layer < info.resources.layers; ++layer) {
@@ -978,7 +978,7 @@ std::vector FullUploadSwizzles(const ImageInfo& info) {
void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const ImageInfo& info,
std::span copies, std::span memory,
- std::vector& tmp_buffer) {
+ Common::ScratchBuffer& tmp_buffer) {
const bool is_pitch_linear = info.type == ImageType::Linear;
for (const BufferImageCopy& copy : copies) {
if (is_pitch_linear) {
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index 2c991b4d2..d103db8ae 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -7,6 +7,7 @@
#include
#include "common/common_types.h"
+#include "common/scratch_buffer.h"
#include "video_core/surface.h"
#include "video_core/texture_cache/image_base.h"
@@ -78,7 +79,7 @@ void ConvertImage(std::span input, const ImageInfo& info, std::span copies, std::span memory,
- std::vector& tmp_buffer);
+ Common::ScratchBuffer& tmp_buffer);
[[nodiscard]] bool IsBlockLinearSizeCompatible(const ImageInfo& new_info,
const ImageInfo& overlap_info, u32 new_level,