summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2021-06-20 12:25:59 +0200
committerGravatar Fernando Sahmkow2021-07-04 22:32:35 +0200
commit8f9f142956bb5de205cad2237f0cf60770796867 (patch)
tree00aa9899f418b73889955da8dfdbb6a9c3c20a27
parentTexture Cache: Improve accuracy of sparse texture detection. (diff)
downloadyuzu-8f9f142956bb5de205cad2237f0cf60770796867.tar.gz
yuzu-8f9f142956bb5de205cad2237f0cf60770796867.tar.xz
yuzu-8f9f142956bb5de205cad2237f0cf60770796867.zip
Texture Cache: Address feedback.
-rw-r--r--src/video_core/memory_manager.cpp1
-rw-r--r--src/video_core/memory_manager.h8
-rw-r--r--src/video_core/rasterizer_interface.h2
-rw-r--r--src/video_core/texture_cache/image_base.h28
-rw-r--r--src/video_core/texture_cache/texture_cache.h16
5 files changed, 37 insertions, 18 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index e66af4443..d2b9d5f2b 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -80,7 +80,6 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) {
80 rasterizer->UnmapMemory(*cpu_addr, map.second); 80 rasterizer->UnmapMemory(*cpu_addr, map.second);
81 } 81 }
82 82
83
84 UpdateRange(gpu_addr, PageEntry::State::Unmapped, size); 83 UpdateRange(gpu_addr, PageEntry::State::Unmapped, size);
85} 84}
86 85
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 305c4b1f1..99d13e7f6 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -114,22 +114,22 @@ public:
114 void WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size); 114 void WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size);
115 115
116 /** 116 /**
117 * IsGranularRange checks if a gpu region can be simply read with a pointer. 117 * Checks if a gpu region can be simply read with a pointer.
118 */ 118 */
119 [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; 119 [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const;
120 120
121 /** 121 /**
122 * IsContinousRange checks if a gpu region is mapped by a single range of cpu addresses. 122 * Checks if a gpu region is mapped by a single range of cpu addresses.
123 */ 123 */
124 [[nodiscard]] bool IsContinousRange(GPUVAddr gpu_addr, std::size_t size) const; 124 [[nodiscard]] bool IsContinousRange(GPUVAddr gpu_addr, std::size_t size) const;
125 125
126 /** 126 /**
127 * IsFullyMappedRange checks if a gpu region is mapped entirely. 127 * Checks if a gpu region is mapped entirely.
128 */ 128 */
129 [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const; 129 [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const;
130 130
131 /** 131 /**
132 * GetSubmappedRange returns a vector with all the subranges of cpu addresses mapped beneath. 132 * Returns a vector with all the subranges of cpu addresses mapped beneath.
133 * if the region is continous, a single pair will be returned. If it's unmapped, an empty vector 133 * if the region is continous, a single pair will be returned. If it's unmapped, an empty vector
134 * will be returned; 134 * will be returned;
135 */ 135 */
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index c0ba32346..0cec4225b 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -87,7 +87,7 @@ public:
87 /// Unmap memory range 87 /// Unmap memory range
88 virtual void UnmapMemory(VAddr addr, u64 size) = 0; 88 virtual void UnmapMemory(VAddr addr, u64 size) = 0;
89 89
90 /// Unmap memory range 90 /// Remap GPU memory range. This means underneath backing memory changed
91 virtual void ModifyGPUMemory(GPUVAddr addr, u64 size) = 0; 91 virtual void ModifyGPUMemory(GPUVAddr addr, u64 size) = 0;
92 92
93 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 93 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index fd14a3980..65e68cbb3 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -26,11 +26,12 @@ enum class ImageFlagBits : u32 {
26 Registered = 1 << 6, ///< True when the image is registered 26 Registered = 1 << 6, ///< True when the image is registered
27 Picked = 1 << 7, ///< Temporary flag to mark the image as picked 27 Picked = 1 << 7, ///< Temporary flag to mark the image as picked
28 Remapped = 1 << 8, ///< Image has been remapped. 28 Remapped = 1 << 8, ///< Image has been remapped.
29 Sparse = 1 << 9, ///< Image has non continous submemory.
29 30
30 // Garbage Collection Flags 31 // Garbage Collection Flags
31 BadOverlap = 1 << 9, ///< This image overlaps other but doesn't fit, has higher 32 BadOverlap = 1 << 10,///< This image overlaps other but doesn't fit, has higher
32 ///< garbage collection priority 33 ///< garbage collection priority
33 Alias = 1 << 10, ///< This image has aliases and has priority on garbage 34 Alias = 1 << 11, ///< This image has aliases and has priority on garbage
34 ///< collection 35 ///< collection
35}; 36};
36DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) 37DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
@@ -92,7 +93,28 @@ struct ImageBase {
92 std::vector<AliasedImage> aliased_images; 93 std::vector<AliasedImage> aliased_images;
93 std::vector<ImageId> overlapping_images; 94 std::vector<ImageId> overlapping_images;
94 ImageMapId map_view_id{}; 95 ImageMapId map_view_id{};
95 bool is_sparse{}; 96};
97
98struct ImageMapView {
99 explicit ImageMapView(GPUVAddr gpu_addr, VAddr cpu_addr, size_t size, ImageId image_id);
100
101 [[nodiscard]] bool Overlaps(VAddr overlap_cpu_addr, size_t overlap_size) const noexcept {
102 const VAddr overlap_end = overlap_cpu_addr + overlap_size;
103 const VAddr cpu_addr_end = cpu_addr + size;
104 return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end;
105 }
106
107 [[nodiscard]] bool OverlapsGPU(GPUVAddr overlap_gpu_addr, size_t overlap_size) const noexcept {
108 const GPUVAddr overlap_end = overlap_gpu_addr + overlap_size;
109 const GPUVAddr gpu_addr_end = gpu_addr + size;
110 return gpu_addr < overlap_end && overlap_gpu_addr < gpu_addr_end;
111 }
112
113 GPUVAddr gpu_addr;
114 VAddr cpu_addr;
115 size_t size;
116 ImageId image_id;
117 bool picked{};
96}; 118};
97 119
98struct ImageAllocBase { 120struct ImageAllocBase {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 1704fc48c..500c4dd52 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -156,9 +156,6 @@ public:
156 /// Remove images in a region 156 /// Remove images in a region
157 void UnmapGPUMemory(GPUVAddr gpu_addr, size_t size); 157 void UnmapGPUMemory(GPUVAddr gpu_addr, size_t size);
158 158
159 /// Used when GPU memory changes layout on sparse textures.
160 // void CheckRemaps();
161
162 /// Blit an image with the given parameters 159 /// Blit an image with the given parameters
163 void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, 160 void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
164 const Tegra::Engines::Fermi2D::Surface& src, 161 const Tegra::Engines::Fermi2D::Surface& src,
@@ -1179,8 +1176,9 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
1179 const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); 1176 const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr);
1180 Image& new_image = slot_images[new_image_id]; 1177 Image& new_image = slot_images[new_image_id];
1181 1178
1182 new_image.is_sparse = 1179 if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) {
1183 !gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes); 1180 new_image.flags |= ImageFlagBits::Sparse;
1181 }
1184 1182
1185 for (const ImageId overlap_id : ignore_textures) { 1183 for (const ImageId overlap_id : ignore_textures) {
1186 Image& overlap = slot_images[overlap_id]; 1184 Image& overlap = slot_images[overlap_id];
@@ -1519,7 +1517,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
1519 total_used_memory += Common::AlignUp(tentative_size, 1024); 1517 total_used_memory += Common::AlignUp(tentative_size, 1024);
1520 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, 1518 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
1521 [this, image_id](u64 page) { gpu_page_table[page].push_back(image_id); }); 1519 [this, image_id](u64 page) { gpu_page_table[page].push_back(image_id); });
1522 if (!image.is_sparse) { 1520 if (False(image.flags & ImageFlagBits::Sparse)) {
1523 auto map_id = 1521 auto map_id =
1524 slot_map_views.insert(image.gpu_addr, image.cpu_addr, image.guest_size_bytes, image_id); 1522 slot_map_views.insert(image.gpu_addr, image.cpu_addr, image.guest_size_bytes, image_id);
1525 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, 1523 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes,
@@ -1574,7 +1572,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
1574 }; 1572 };
1575 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, 1573 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
1576 [this, &clear_page_table](u64 page) { clear_page_table(page, gpu_page_table); }); 1574 [this, &clear_page_table](u64 page) { clear_page_table(page, gpu_page_table); });
1577 if (!image.is_sparse) { 1575 if (False(image.flags & ImageFlagBits::Sparse)) {
1578 const auto map_id = image.map_view_id; 1576 const auto map_id = image.map_view_id;
1579 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, [this, map_id](u64 page) { 1577 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, [this, map_id](u64 page) {
1580 const auto page_it = page_table.find(page); 1578 const auto page_it = page_table.find(page);
@@ -1633,7 +1631,7 @@ template <class P>
1633void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { 1631void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
1634 ASSERT(False(image.flags & ImageFlagBits::Tracked)); 1632 ASSERT(False(image.flags & ImageFlagBits::Tracked));
1635 image.flags |= ImageFlagBits::Tracked; 1633 image.flags |= ImageFlagBits::Tracked;
1636 if (!image.is_sparse) { 1634 if (False(image.flags & ImageFlagBits::Sparse)) {
1637 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); 1635 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1);
1638 return; 1636 return;
1639 } 1637 }
@@ -1659,7 +1657,7 @@ template <class P>
1659void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { 1657void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
1660 ASSERT(True(image.flags & ImageFlagBits::Tracked)); 1658 ASSERT(True(image.flags & ImageFlagBits::Tracked));
1661 image.flags &= ~ImageFlagBits::Tracked; 1659 image.flags &= ~ImageFlagBits::Tracked;
1662 if (!image.is_sparse) { 1660 if (False(image.flags & ImageFlagBits::Sparse)) {
1663 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); 1661 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1);
1664 return; 1662 return;
1665 } 1663 }