diff options
| author | 2021-11-28 12:16:31 +0100 | |
|---|---|---|
| committer | 2021-11-28 12:16:31 +0100 | |
| commit | 3031223153d2b11d089acf5c50718372b5c24b6b (patch) | |
| tree | cc459170f6a363e3e25a9bcf9d95316ec66093f7 /src/video_core/texture_cache | |
| parent | Merge pull request #7438 from german77/homebrew2 (diff) | |
| parent | Texture Cache: Secure insertions against deletions. (diff) | |
| download | yuzu-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.h | 96 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 3 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.cpp | 20 |
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> | |||
| 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,32 +1091,58 @@ 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, |
| 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> | |||
| 1160 | ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr, | 1199 | ImageViewId 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 | ||
| 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; | ||
| 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 | ||
| 1189 | u32 MapSizeBytes(const ImageBase& image) { | 1175 | u32 MapSizeBytes(const ImageBase& image) { |