diff options
| author | 2021-11-26 21:36:53 +0100 | |
|---|---|---|
| committer | 2021-11-27 11:22:16 +0100 | |
| commit | ecefc932e64bf4ab8442d3c9808a2e54429e7001 (patch) | |
| tree | 5c89e97f5893905cfc490ef3a7d67ae066be23ae | |
| parent | Texture Cache: Further fix regressions. (diff) | |
| download | yuzu-ecefc932e64bf4ab8442d3c9808a2e54429e7001.tar.gz yuzu-ecefc932e64bf4ab8442d3c9808a2e54429e7001.tar.xz yuzu-ecefc932e64bf4ab8442d3c9808a2e54429e7001.zip | |
Texture Cache: Redesigning the blitting system (again).
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 52 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 3 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.cpp | 32 |
3 files changed, 64 insertions, 23 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 570da2b04..f24de9a38 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> | |||
| 472 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 472 | void 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 | ||
| 792 | template <class P> | 805 | template <class P> |
| @@ -1078,17 +1091,26 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 1078 | 1091 | ||
| 1079 | template <class P> | 1092 | template <class P> |
| 1080 | typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( | 1093 | typename 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, |
| 1095 | const Tegra::Engines::Fermi2D::Config& copy) { | ||
| 1096 | |||
| 1082 | static constexpr auto FIND_OPTIONS = RelaxedOptions::Samples; | 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 | src_id = FindImage(src_info, src_addr, FIND_OPTIONS); | 1112 | src_id = FindImage(src_info, src_addr, try_options); |
| 1113 | dst_id = FindImage(dst_info, dst_addr, try_options); | ||
| 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 | if (src_image && src_image->info.num_samples > 1) { | 1115 | if (src_image && src_image->info.num_samples > 1) { |
| 1094 | RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews}; | 1116 | RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews}; |
| @@ -1097,8 +1119,15 @@ typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( | |||
| 1097 | if (has_deleted_images) { | 1119 | if (has_deleted_images) { |
| 1098 | continue; | 1120 | continue; |
| 1099 | } | 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 | } | ||
| 1100 | } | 1130 | } |
| 1101 | dst_id = FindImage(dst_info, dst_addr, FIND_OPTIONS); | ||
| 1102 | if (!src_id) { | 1131 | if (!src_id) { |
| 1103 | src_id = InsertImage(src_info, src_addr, RelaxedOptions{}); | 1132 | src_id = InsertImage(src_info, src_addr, RelaxedOptions{}); |
| 1104 | } | 1133 | } |
| @@ -1106,6 +1135,11 @@ typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages( | |||
| 1106 | dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{}); | 1135 | dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{}); |
| 1107 | } | 1136 | } |
| 1108 | } 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 | src_id = FindOrInsertImage(src_info, src_addr, RelaxedOptions{}); | ||
| 1141 | dst_id = FindOrInsertImage(dst_info, dst_addr, RelaxedOptions{}); | ||
| 1142 | } | ||
| 1109 | return BlitImages{ | 1143 | return BlitImages{ |
| 1110 | .dst_id = dst_id, | 1144 | .dst_id = dst_id, |
| 1111 | .src_id = src_id, | 1145 | .src_id = src_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 9b1613008..7bd31b211 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -1151,19 +1151,25 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr | |||
| 1151 | 1151 | ||
| 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, | 1152 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, |
| 1153 | const ImageBase* src) { | 1153 | const ImageBase* src) { |
| 1154 | bool is_resolve = false; | 1154 | const auto original_dst_format = dst_info.format; |
| 1155 | if (src) { | 1155 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { |
| 1156 | is_resolve = src->info.num_samples > 1; | 1156 | src_info.format = src->info.format; |
| 1157 | src_info.num_samples = src->info.num_samples; | 1157 | } |
| 1158 | src_info.size.width = src->info.size.width; | 1158 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1159 | src_info.size.height = src->info.size.height; | 1159 | dst_info.format = dst->info.format; |
| 1160 | } | 1160 | } |
| 1161 | if (dst) { | 1161 | if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { |
| 1162 | dst_info.num_samples = dst->info.num_samples; | 1162 | dst_info.format = src->info.format; |
| 1163 | dst_info.size.width = dst->info.size.width; | 1163 | } |
| 1164 | dst_info.size.height = dst->info.size.height; | 1164 | if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { |
| 1165 | } | 1165 | if (src) { |
| 1166 | ASSERT(!is_resolve || dst_info.format == src_info.format); | 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 | } | ||
| 1172 | } | ||
| 1167 | } | 1173 | } |
| 1168 | 1174 | ||
| 1169 | u32 MapSizeBytes(const ImageBase& image) { | 1175 | u32 MapSizeBytes(const ImageBase& image) { |