summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Feng Chen2021-12-18 13:57:14 +0800
committerGravatar GitHub2021-12-18 13:57:14 +0800
commite49184e6069a9d791d2df3c1958f5c4b1187e124 (patch)
treeb776caf722e0be0e680f67b0ad0842628162ef1c /src/video_core/texture_cache
parentImplement convert legacy to generic (diff)
parentMerge pull request #7570 from ameerj/favorites-expanded (diff)
downloadyuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.gz
yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.xz
yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.zip
Merge branch 'yuzu-emu:master' into convert_legacy
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp2
-rw-r--r--src/video_core/texture_cache/formatter.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h105
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h5
-rw-r--r--src/video_core/texture_cache/types.h1
-rw-r--r--src/video_core/texture_cache/util.cpp9
6 files changed, 99 insertions, 25 deletions
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index ddfb726fe..afa807d5d 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -139,6 +139,8 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
139 return PixelFormat::D16_UNORM; 139 return PixelFormat::D16_UNORM;
140 case Hash(TextureFormat::S8D24, UINT, UNORM, UNORM, UNORM, LINEAR): 140 case Hash(TextureFormat::S8D24, UINT, UNORM, UNORM, UNORM, LINEAR):
141 return PixelFormat::S8_UINT_D24_UNORM; 141 return PixelFormat::S8_UINT_D24_UNORM;
142 case Hash(TextureFormat::S8D24, UINT, UNORM, UINT, UINT, LINEAR):
143 return PixelFormat::S8_UINT_D24_UNORM;
142 case Hash(TextureFormat::R8G24, UINT, UNORM, UNORM, UNORM, LINEAR): 144 case Hash(TextureFormat::R8G24, UINT, UNORM, UNORM, UNORM, LINEAR):
143 return PixelFormat::S8_UINT_D24_UNORM; 145 return PixelFormat::S8_UINT_D24_UNORM;
144 case Hash(TextureFormat::D32S8, FLOAT, UINT, UNORM, UNORM, LINEAR): 146 case Hash(TextureFormat::D32S8, FLOAT, UINT, UNORM, UNORM, LINEAR):
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h
index c6cf0583f..b2c81057b 100644
--- a/src/video_core/texture_cache/formatter.h
+++ b/src/video_core/texture_cache/formatter.h
@@ -194,6 +194,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str
194 return "D32_FLOAT"; 194 return "D32_FLOAT";
195 case PixelFormat::D16_UNORM: 195 case PixelFormat::D16_UNORM:
196 return "D16_UNORM"; 196 return "D16_UNORM";
197 case PixelFormat::S8_UINT:
198 return "S8_UINT";
197 case PixelFormat::D24_UNORM_S8_UINT: 199 case PixelFormat::D24_UNORM_S8_UINT:
198 return "D24_UNORM_S8_UINT"; 200 return "D24_UNORM_S8_UINT";
199 case PixelFormat::S8_UINT_D24_UNORM: 201 case PixelFormat::S8_UINT_D24_UNORM:
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 241f71a91..5aaeb16ca 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -472,9 +472,10 @@ template <class P>
472void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, 472void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
473 const Tegra::Engines::Fermi2D::Surface& src, 473 const Tegra::Engines::Fermi2D::Surface& src,
474 const Tegra::Engines::Fermi2D::Config& copy) { 474 const Tegra::Engines::Fermi2D::Config& copy) {
475 const BlitImages images = GetBlitImages(dst, src); 475 const BlitImages images = GetBlitImages(dst, src, copy);
476 const ImageId dst_id = images.dst_id; 476 const ImageId dst_id = images.dst_id;
477 const ImageId src_id = images.src_id; 477 const ImageId src_id = images.src_id;
478
478 PrepareImage(src_id, false, false); 479 PrepareImage(src_id, false, false);
479 PrepareImage(dst_id, true, false); 480 PrepareImage(dst_id, true, false);
480 481
@@ -758,14 +759,18 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
758 return ImageId{}; 759 return ImageId{};
759 } 760 }
760 } 761 }
761 const bool broken_views = runtime.HasBrokenTextureViewFormats(); 762 const bool broken_views =
763 runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews);
762 const bool native_bgr = runtime.HasNativeBgr(); 764 const bool native_bgr = runtime.HasNativeBgr();
763 ImageId image_id; 765 const bool flexible_formats = True(options & RelaxedOptions::Format);
766 ImageId image_id{};
767 boost::container::small_vector<ImageId, 1> image_ids;
764 const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { 768 const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) {
765 if (True(existing_image.flags & ImageFlagBits::Remapped)) { 769 if (True(existing_image.flags & ImageFlagBits::Remapped)) {
766 return false; 770 return false;
767 } 771 }
768 if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear) { 772 if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear)
773 [[unlikely]] {
769 const bool strict_size = False(options & RelaxedOptions::Size) && 774 const bool strict_size = False(options & RelaxedOptions::Size) &&
770 True(existing_image.flags & ImageFlagBits::Strong); 775 True(existing_image.flags & ImageFlagBits::Strong);
771 const ImageInfo& existing = existing_image.info; 776 const ImageInfo& existing = existing_image.info;
@@ -774,17 +779,27 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
774 IsPitchLinearSameSize(existing, info, strict_size) && 779 IsPitchLinearSameSize(existing, info, strict_size) &&
775 IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) { 780 IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) {
776 image_id = existing_image_id; 781 image_id = existing_image_id;
777 return true; 782 image_ids.push_back(existing_image_id);
783 return !flexible_formats && existing.format == info.format;
778 } 784 }
779 } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views, 785 } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views,
780 native_bgr)) { 786 native_bgr)) {
781 image_id = existing_image_id; 787 image_id = existing_image_id;
782 return true; 788 image_ids.push_back(existing_image_id);
789 return !flexible_formats && existing_image.info.format == info.format;
783 } 790 }
784 return false; 791 return false;
785 }; 792 };
786 ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda); 793 ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda);
787 return image_id; 794 if (image_ids.size() <= 1) [[likely]] {
795 return image_id;
796 }
797 auto image_ids_compare = [this](ImageId a, ImageId b) {
798 auto& image_a = slot_images[a];
799 auto& image_b = slot_images[b];
800 return image_a.modification_tick < image_b.modification_tick;
801 };
802 return *std::ranges::max_element(image_ids, image_ids_compare);
788} 803}
789 804
790template <class P> 805template <class P>
@@ -1076,31 +1091,66 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
1076 1091
1077template <class P> 1092template <class P>
1078typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( 1093typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages(
1079 const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src) { 1094 const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src,
1080 static constexpr auto FIND_OPTIONS = RelaxedOptions::Format | RelaxedOptions::Samples; 1095 const Tegra::Engines::Fermi2D::Config& copy) {
1096
1097 static constexpr auto FIND_OPTIONS = RelaxedOptions::Samples;
1081 const GPUVAddr dst_addr = dst.Address(); 1098 const GPUVAddr dst_addr = dst.Address();
1082 const GPUVAddr src_addr = src.Address(); 1099 const GPUVAddr src_addr = src.Address();
1083 ImageInfo dst_info(dst); 1100 ImageInfo dst_info(dst);
1084 ImageInfo src_info(src); 1101 ImageInfo src_info(src);
1102 const bool can_be_depth_blit =
1103 dst_info.format == src_info.format && copy.filter == Tegra::Engines::Fermi2D::Filter::Point;
1085 ImageId dst_id; 1104 ImageId dst_id;
1086 ImageId src_id; 1105 ImageId src_id;
1106 RelaxedOptions try_options = FIND_OPTIONS;
1107 if (can_be_depth_blit) {
1108 try_options |= RelaxedOptions::Format;
1109 }
1087 do { 1110 do {
1088 has_deleted_images = false; 1111 has_deleted_images = false;
1089 dst_id = FindImage(dst_info, dst_addr, FIND_OPTIONS); 1112 src_id = FindImage(src_info, src_addr, try_options);
1090 src_id = FindImage(src_info, src_addr, FIND_OPTIONS); 1113 dst_id = FindImage(dst_info, dst_addr, try_options);
1091 const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
1092 const ImageBase* const src_image = src_id ? &slot_images[src_id] : nullptr; 1114 const ImageBase* const src_image = src_id ? &slot_images[src_id] : nullptr;
1093 DeduceBlitImages(dst_info, src_info, dst_image, src_image); 1115 if (src_image && src_image->info.num_samples > 1) {
1094 if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { 1116 RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews};
1095 continue; 1117 src_id = FindOrInsertImage(src_info, src_addr, find_options);
1118 dst_id = FindOrInsertImage(dst_info, dst_addr, find_options);
1119 if (has_deleted_images) {
1120 continue;
1121 }
1122 break;
1096 } 1123 }
1097 if (!dst_id) { 1124 if (can_be_depth_blit) {
1098 dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{}); 1125 const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
1126 DeduceBlitImages(dst_info, src_info, dst_image, src_image);
1127 if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) {
1128 continue;
1129 }
1099 } 1130 }
1100 if (!src_id) { 1131 if (!src_id) {
1101 src_id = InsertImage(src_info, src_addr, RelaxedOptions{}); 1132 src_id = InsertImage(src_info, src_addr, RelaxedOptions{});
1102 } 1133 }
1134 if (!dst_id) {
1135 dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{});
1136 }
1103 } while (has_deleted_images); 1137 } while (has_deleted_images);
1138 const ImageBase& src_image = slot_images[src_id];
1139 const ImageBase& dst_image = slot_images[dst_id];
1140 const bool native_bgr = runtime.HasNativeBgr();
1141 if (GetFormatType(dst_info.format) != GetFormatType(dst_image.info.format) ||
1142 GetFormatType(src_info.format) != GetFormatType(src_image.info.format) ||
1143 !VideoCore::Surface::IsViewCompatible(dst_info.format, dst_image.info.format, false,
1144 native_bgr) ||
1145 !VideoCore::Surface::IsViewCompatible(src_info.format, src_image.info.format, false,
1146 native_bgr)) {
1147 // Make sure the images match the expected format.
1148 do {
1149 has_deleted_images = false;
1150 src_id = FindOrInsertImage(src_info, src_addr, RelaxedOptions{});
1151 dst_id = FindOrInsertImage(dst_info, dst_addr, RelaxedOptions{});
1152 } while (has_deleted_images);
1153 }
1104 return BlitImages{ 1154 return BlitImages{
1105 .dst_id = dst_id, 1155 .dst_id = dst_id,
1106 .src_id = src_id, 1156 .src_id = src_id,
@@ -1157,7 +1207,14 @@ template <class P>
1157ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr, 1207ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr,
1158 bool is_clear) { 1208 bool is_clear) {
1159 const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{}; 1209 const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{};
1160 const ImageId image_id = FindOrInsertImage(info, gpu_addr, options); 1210 ImageId image_id{};
1211 bool delete_state = has_deleted_images;
1212 do {
1213 has_deleted_images = false;
1214 image_id = FindOrInsertImage(info, gpu_addr, options);
1215 delete_state |= has_deleted_images;
1216 } while (has_deleted_images);
1217 has_deleted_images = delete_state;
1161 if (!image_id) { 1218 if (!image_id) {
1162 return NULL_IMAGE_VIEW_ID; 1219 return NULL_IMAGE_VIEW_ID;
1163 } 1220 }
@@ -1759,8 +1816,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1759 } 1816 }
1760 UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); 1817 UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D);
1761 UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); 1818 UNIMPLEMENTED_IF(src.info.type != ImageType::e2D);
1762 if constexpr (HAS_PIXEL_FORMAT_CONVERSIONS) { 1819 if (runtime.ShouldReinterpret(dst, src)) {
1763 return runtime.ConvertImage(dst, src, copies); 1820 return runtime.ReinterpretImage(dst, src, copies);
1764 } 1821 }
1765 for (const ImageCopy& copy : copies) { 1822 for (const ImageCopy& copy : copies) {
1766 UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); 1823 UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1);
@@ -1780,7 +1837,13 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1780 const SubresourceExtent src_extent{.levels = 1, .layers = 1}; 1837 const SubresourceExtent src_extent{.levels = 1, .layers = 1};
1781 const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent}; 1838 const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent};
1782 const SubresourceRange src_range{.base = src_base, .extent = src_extent}; 1839 const SubresourceRange src_range{.base = src_base, .extent = src_extent};
1783 const ImageViewInfo dst_view_info(ImageViewType::e2D, dst.info.format, dst_range); 1840 PixelFormat dst_format = dst.info.format;
1841 if (GetFormatType(src.info.format) == SurfaceType::DepthStencil &&
1842 GetFormatType(dst_format) == SurfaceType::ColorTexture &&
1843 BytesPerBlock(dst_format) == 4) {
1844 dst_format = PixelFormat::A8B8G8R8_UNORM;
1845 }
1846 const ImageViewInfo dst_view_info(ImageViewType::e2D, dst_format, dst_range);
1784 const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range); 1847 const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range);
1785 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); 1848 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
1786 Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; 1849 Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index a9504c0e8..7107887a6 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -59,8 +59,6 @@ class TextureCache {
59 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; 59 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES;
60 /// True when the API can provide info about the memory of the device. 60 /// True when the API can provide info about the memory of the device.
61 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; 61 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
62 /// True when the API provides utilities for pixel format conversions.
63 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = P::HAS_PIXEL_FORMAT_CONVERSIONS;
64 62
65 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; 63 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB;
66 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; 64 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB;
@@ -254,7 +252,8 @@ private:
254 252
255 /// Return a blit image pair from the given guest blit parameters 253 /// Return a blit image pair from the given guest blit parameters
256 [[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst, 254 [[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst,
257 const Tegra::Engines::Fermi2D::Surface& src); 255 const Tegra::Engines::Fermi2D::Surface& src,
256 const Tegra::Engines::Fermi2D::Config& copy);
258 257
259 /// Find or create a sampler from a guest descriptor sampler 258 /// Find or create a sampler from a guest descriptor sampler
260 [[nodiscard]] SamplerId FindSampler(const TSCEntry& config); 259 [[nodiscard]] SamplerId FindSampler(const TSCEntry& config);
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h
index 5c274abdf..5ac27b3a7 100644
--- a/src/video_core/texture_cache/types.h
+++ b/src/video_core/texture_cache/types.h
@@ -54,6 +54,7 @@ enum class RelaxedOptions : u32 {
54 Size = 1 << 0, 54 Size = 1 << 0,
55 Format = 1 << 1, 55 Format = 1 << 1,
56 Samples = 1 << 2, 56 Samples = 1 << 2,
57 ForceBrokenViews = 1 << 3,
57}; 58};
58DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) 59DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions)
59 60
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index ddc9fb13a..7bd31b211 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1151,6 +1151,7 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr
1151 1151
1152void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, 1152void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst,
1153 const ImageBase* src) { 1153 const ImageBase* src) {
1154 const auto original_dst_format = dst_info.format;
1154 if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { 1155 if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
1155 src_info.format = src->info.format; 1156 src_info.format = src->info.format;
1156 } 1157 }
@@ -1161,7 +1162,13 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
1161 dst_info.format = src->info.format; 1162 dst_info.format = src->info.format;
1162 } 1163 }
1163 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { 1164 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
1164 src_info.format = dst->info.format; 1165 if (src) {
1166 if (GetFormatType(src->info.format) == SurfaceType::ColorTexture) {
1167 dst_info.format = original_dst_format;
1168 }
1169 } else {
1170 src_info.format = dst->info.format;
1171 }
1165 } 1172 }
1166} 1173}
1167 1174