summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando S2021-11-28 12:16:31 +0100
committerGravatar GitHub2021-11-28 12:16:31 +0100
commit3031223153d2b11d089acf5c50718372b5c24b6b (patch)
treecc459170f6a363e3e25a9bcf9d95316ec66093f7 /src/video_core/texture_cache
parentMerge pull request #7438 from german77/homebrew2 (diff)
parentTexture Cache: Secure insertions against deletions. (diff)
downloadyuzu-3031223153d2b11d089acf5c50718372b5c24b6b.tar.gz
yuzu-3031223153d2b11d089acf5c50718372b5c24b6b.tar.xz
yuzu-3031223153d2b11d089acf5c50718372b5c24b6b.zip
Merge pull request #7396 from FernandoS27/blit-this-mf
TextureCache: Eliminate format deduction as full depth conversion has been supported.
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/texture_cache.h96
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h3
-rw-r--r--src/video_core/texture_cache/util.cpp20
3 files changed, 79 insertions, 40 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 44a0d42ba..565b99254 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -472,7 +472,7 @@ 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
@@ -762,12 +762,15 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
762 const bool broken_views = 762 const bool broken_views =
763 runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews); 763 runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews);
764 const bool native_bgr = runtime.HasNativeBgr(); 764 const bool native_bgr = runtime.HasNativeBgr();
765 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;
766 const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { 768 const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) {
767 if (True(existing_image.flags & ImageFlagBits::Remapped)) { 769 if (True(existing_image.flags & ImageFlagBits::Remapped)) {
768 return false; 770 return false;
769 } 771 }
770 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]] {
771 const bool strict_size = False(options & RelaxedOptions::Size) && 774 const bool strict_size = False(options & RelaxedOptions::Size) &&
772 True(existing_image.flags & ImageFlagBits::Strong); 775 True(existing_image.flags & ImageFlagBits::Strong);
773 const ImageInfo& existing = existing_image.info; 776 const ImageInfo& existing = existing_image.info;
@@ -776,17 +779,27 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
776 IsPitchLinearSameSize(existing, info, strict_size) && 779 IsPitchLinearSameSize(existing, info, strict_size) &&
777 IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) { 780 IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) {
778 image_id = existing_image_id; 781 image_id = existing_image_id;
779 return true; 782 image_ids.push_back(existing_image_id);
783 return !flexible_formats && existing.format == info.format;
780 } 784 }
781 } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views, 785 } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views,
782 native_bgr)) { 786 native_bgr)) {
783 image_id = existing_image_id; 787 image_id = existing_image_id;
784 return true; 788 image_ids.push_back(existing_image_id);
789 return !flexible_formats && existing_image.info.format == info.format;
785 } 790 }
786 return false; 791 return false;
787 }; 792 };
788 ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda); 793 ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda);
789 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);
790} 803}
791 804
792template <class P> 805template <class P>
@@ -1078,32 +1091,58 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
1078 1091
1079template <class P> 1092template <class P>
1080typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( 1093typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages(
1081 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,
1082 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;
1083 const GPUVAddr dst_addr = dst.Address(); 1098 const GPUVAddr dst_addr = dst.Address();
1084 const GPUVAddr src_addr = src.Address(); 1099 const GPUVAddr src_addr = src.Address();
1085 ImageInfo dst_info(dst); 1100 ImageInfo dst_info(dst);
1086 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;
1087 ImageId dst_id; 1104 ImageId dst_id;
1088 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 }
1089 do { 1110 do {
1090 has_deleted_images = false; 1111 has_deleted_images = false;
1091 dst_id = FindImage(dst_info, dst_addr, FIND_OPTIONS); 1112 src_id = FindImage(src_info, src_addr, try_options);
1092 src_id = FindImage(src_info, src_addr, FIND_OPTIONS); 1113 dst_id = FindImage(dst_info, dst_addr, try_options);
1093 const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
1094 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;
1095 DeduceBlitImages(dst_info, src_info, dst_image, src_image); 1115 if (src_image && src_image->info.num_samples > 1) {
1096 if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) { 1116 RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews};
1097 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;
1123 }
1124 if (can_be_depth_blit) {
1125 const ImageBase* const dst_image = src_id ? &slot_images[src_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 }
1130 }
1131 if (!src_id) {
1132 src_id = InsertImage(src_info, src_addr, RelaxedOptions{});
1098 } 1133 }
1099 RelaxedOptions find_options{}; 1134 if (!dst_id) {
1100 if (src_info.num_samples > 1) { 1135 dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{});
1101 // it's a resolve, we must enforce the same format.
1102 find_options = RelaxedOptions::ForceBrokenViews;
1103 } 1136 }
1104 src_id = FindOrInsertImage(src_info, src_addr, find_options);
1105 dst_id = FindOrInsertImage(dst_info, dst_addr, find_options);
1106 } while (has_deleted_images); 1137 } while (has_deleted_images);
1138 if (GetFormatType(dst_info.format) != SurfaceType::ColorTexture) {
1139 // Make sure the images are depth and/or stencil textures.
1140 do {
1141 has_deleted_images = false;
1142 src_id = FindOrInsertImage(src_info, src_addr, RelaxedOptions{});
1143 dst_id = FindOrInsertImage(dst_info, dst_addr, RelaxedOptions{});
1144 } while (has_deleted_images);
1145 }
1107 return BlitImages{ 1146 return BlitImages{
1108 .dst_id = dst_id, 1147 .dst_id = dst_id,
1109 .src_id = src_id, 1148 .src_id = src_id,
@@ -1160,7 +1199,14 @@ template <class P>
1160ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr, 1199ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr,
1161 bool is_clear) { 1200 bool is_clear) {
1162 const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{}; 1201 const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{};
1163 const ImageId image_id = FindOrInsertImage(info, gpu_addr, options); 1202 ImageId image_id{};
1203 bool delete_state = has_deleted_images;
1204 do {
1205 has_deleted_images = false;
1206 image_id = FindOrInsertImage(info, gpu_addr, options);
1207 delete_state |= has_deleted_images;
1208 } while (has_deleted_images);
1209 has_deleted_images = delete_state;
1164 if (!image_id) { 1210 if (!image_id) {
1165 return NULL_IMAGE_VIEW_ID; 1211 return NULL_IMAGE_VIEW_ID;
1166 } 1212 }
@@ -1783,7 +1829,13 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1783 const SubresourceExtent src_extent{.levels = 1, .layers = 1}; 1829 const SubresourceExtent src_extent{.levels = 1, .layers = 1};
1784 const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent}; 1830 const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent};
1785 const SubresourceRange src_range{.base = src_base, .extent = src_extent}; 1831 const SubresourceRange src_range{.base = src_base, .extent = src_extent};
1786 const ImageViewInfo dst_view_info(ImageViewType::e2D, dst.info.format, dst_range); 1832 PixelFormat dst_format = dst.info.format;
1833 if (GetFormatType(src.info.format) == SurfaceType::DepthStencil &&
1834 GetFormatType(dst_format) == SurfaceType::ColorTexture &&
1835 BytesPerBlock(dst_format) == 4) {
1836 dst_format = PixelFormat::A8B8G8R8_UNORM;
1837 }
1838 const ImageViewInfo dst_view_info(ImageViewType::e2D, dst_format, dst_range);
1787 const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range); 1839 const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range);
1788 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); 1840 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
1789 Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; 1841 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 643ad811c..7107887a6 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -252,7 +252,8 @@ private:
252 252
253 /// Return a blit image pair from the given guest blit parameters 253 /// Return a blit image pair from the given guest blit parameters
254 [[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst, 254 [[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst,
255 const Tegra::Engines::Fermi2D::Surface& src); 255 const Tegra::Engines::Fermi2D::Surface& src,
256 const Tegra::Engines::Fermi2D::Config& copy);
256 257
257 /// Find or create a sampler from a guest descriptor sampler 258 /// Find or create a sampler from a guest descriptor sampler
258 [[nodiscard]] SamplerId FindSampler(const TSCEntry& config); 259 [[nodiscard]] SamplerId FindSampler(const TSCEntry& config);
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index e4d82631e..7bd31b211 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1151,28 +1151,15 @@ 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 bool is_resolve = false;
1155 const auto original_src_format = src_info.format;
1156 const auto original_dst_format = dst_info.format; 1154 const auto original_dst_format = dst_info.format;
1157 if (src) { 1155 if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
1158 if (GetFormatType(src->info.format) != SurfaceType::ColorTexture) { 1156 src_info.format = src->info.format;
1159 src_info.format = src->info.format;
1160 }
1161 is_resolve = src->info.num_samples > 1;
1162 src_info.num_samples = src->info.num_samples;
1163 src_info.size = src->info.size;
1164 } 1157 }
1165 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { 1158 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
1166 dst_info.format = dst->info.format; 1159 dst_info.format = dst->info.format;
1167 } 1160 }
1168 if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { 1161 if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
1169 if (dst) { 1162 dst_info.format = src->info.format;
1170 if (GetFormatType(dst->info.format) == SurfaceType::ColorTexture) {
1171 src_info.format = original_src_format;
1172 }
1173 } else {
1174 dst_info.format = src->info.format;
1175 }
1176 } 1163 }
1177 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { 1164 if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
1178 if (src) { 1165 if (src) {
@@ -1183,7 +1170,6 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
1183 src_info.format = dst->info.format; 1170 src_info.format = dst->info.format;
1184 } 1171 }
1185 } 1172 }
1186 ASSERT(!is_resolve || dst_info.format == src_info.format);
1187} 1173}
1188 1174
1189u32 MapSizeBytes(const ImageBase& image) { 1175u32 MapSizeBytes(const ImageBase& image) {