diff options
| author | 2023-05-07 19:05:56 -0400 | |
|---|---|---|
| committer | 2023-05-07 19:05:56 -0400 | |
| commit | 2688fb1aa2d80fc4edac87ff93365f3570cd3af8 (patch) | |
| tree | b874061d30aa6a03fd3c92116df92ed6d3b91a19 /src/video_core/texture_cache | |
| parent | Merge pull request #10097 from german77/nfp_full (diff) | |
| parent | Texture cache: Only force flush the dma downloads (diff) | |
| download | yuzu-2688fb1aa2d80fc4edac87ff93365f3570cd3af8.tar.gz yuzu-2688fb1aa2d80fc4edac87ff93365f3570cd3af8.tar.xz yuzu-2688fb1aa2d80fc4edac87ff93365f3570cd3af8.zip | |
Merge pull request #10155 from FernandoS27/reactive-flushing-new
Y.F.C. bring back Reactive Flushing
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/image_info.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_info.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_view_base.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 45 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 4 |
5 files changed, 59 insertions, 8 deletions
diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 11f3f78a1..e8ddde691 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <fmt/format.h> | 4 | #include <fmt/format.h> |
| 5 | 5 | ||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/settings.h" | ||
| 7 | #include "video_core/surface.h" | 8 | #include "video_core/surface.h" |
| 8 | #include "video_core/texture_cache/format_lookup_table.h" | 9 | #include "video_core/texture_cache/format_lookup_table.h" |
| 9 | #include "video_core/texture_cache/image_info.h" | 10 | #include "video_core/texture_cache/image_info.h" |
| @@ -22,6 +23,8 @@ using VideoCore::Surface::PixelFormat; | |||
| 22 | using VideoCore::Surface::SurfaceType; | 23 | using VideoCore::Surface::SurfaceType; |
| 23 | 24 | ||
| 24 | ImageInfo::ImageInfo(const TICEntry& config) noexcept { | 25 | ImageInfo::ImageInfo(const TICEntry& config) noexcept { |
| 26 | forced_flushed = config.IsPitchLinear() && !Settings::values.use_reactive_flushing.GetValue(); | ||
| 27 | dma_downloaded = forced_flushed; | ||
| 25 | format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type, | 28 | format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type, |
| 26 | config.a_type, config.srgb_conversion); | 29 | config.a_type, config.srgb_conversion); |
| 27 | num_samples = NumSamples(config.msaa_mode); | 30 | num_samples = NumSamples(config.msaa_mode); |
| @@ -117,6 +120,9 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { | |||
| 117 | 120 | ||
| 118 | ImageInfo::ImageInfo(const Maxwell3D::Regs::RenderTargetConfig& ct, | 121 | ImageInfo::ImageInfo(const Maxwell3D::Regs::RenderTargetConfig& ct, |
| 119 | Tegra::Texture::MsaaMode msaa_mode) noexcept { | 122 | Tegra::Texture::MsaaMode msaa_mode) noexcept { |
| 123 | forced_flushed = | ||
| 124 | ct.tile_mode.is_pitch_linear && !Settings::values.use_reactive_flushing.GetValue(); | ||
| 125 | dma_downloaded = forced_flushed; | ||
| 120 | format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(ct.format); | 126 | format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(ct.format); |
| 121 | rescaleable = false; | 127 | rescaleable = false; |
| 122 | if (ct.tile_mode.is_pitch_linear) { | 128 | if (ct.tile_mode.is_pitch_linear) { |
| @@ -155,6 +161,9 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs::RenderTargetConfig& ct, | |||
| 155 | 161 | ||
| 156 | ImageInfo::ImageInfo(const Maxwell3D::Regs::Zeta& zt, const Maxwell3D::Regs::ZetaSize& zt_size, | 162 | ImageInfo::ImageInfo(const Maxwell3D::Regs::Zeta& zt, const Maxwell3D::Regs::ZetaSize& zt_size, |
| 157 | Tegra::Texture::MsaaMode msaa_mode) noexcept { | 163 | Tegra::Texture::MsaaMode msaa_mode) noexcept { |
| 164 | forced_flushed = | ||
| 165 | zt.tile_mode.is_pitch_linear && !Settings::values.use_reactive_flushing.GetValue(); | ||
| 166 | dma_downloaded = forced_flushed; | ||
| 158 | format = VideoCore::Surface::PixelFormatFromDepthFormat(zt.format); | 167 | format = VideoCore::Surface::PixelFormatFromDepthFormat(zt.format); |
| 159 | size.width = zt_size.width; | 168 | size.width = zt_size.width; |
| 160 | size.height = zt_size.height; | 169 | size.height = zt_size.height; |
| @@ -195,6 +204,9 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs::Zeta& zt, const Maxwell3D::Regs::Zet | |||
| 195 | 204 | ||
| 196 | ImageInfo::ImageInfo(const Fermi2D::Surface& config) noexcept { | 205 | ImageInfo::ImageInfo(const Fermi2D::Surface& config) noexcept { |
| 197 | UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero"); | 206 | UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero"); |
| 207 | forced_flushed = config.linear == Fermi2D::MemoryLayout::Pitch && | ||
| 208 | !Settings::values.use_reactive_flushing.GetValue(); | ||
| 209 | dma_downloaded = forced_flushed; | ||
| 198 | format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format); | 210 | format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format); |
| 199 | rescaleable = false; | 211 | rescaleable = false; |
| 200 | if (config.linear == Fermi2D::MemoryLayout::Pitch) { | 212 | if (config.linear == Fermi2D::MemoryLayout::Pitch) { |
diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 4b7dfa315..8a4cb0cbd 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h | |||
| @@ -39,6 +39,8 @@ struct ImageInfo { | |||
| 39 | u32 tile_width_spacing = 0; | 39 | u32 tile_width_spacing = 0; |
| 40 | bool rescaleable = false; | 40 | bool rescaleable = false; |
| 41 | bool downscaleable = false; | 41 | bool downscaleable = false; |
| 42 | bool forced_flushed = false; | ||
| 43 | bool dma_downloaded = false; | ||
| 42 | }; | 44 | }; |
| 43 | 45 | ||
| 44 | } // namespace VideoCommon | 46 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index bcad40353..d134b6738 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | 5 | ||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/settings.h" | ||
| 8 | #include "video_core/compatible_formats.h" | 7 | #include "video_core/compatible_formats.h" |
| 9 | #include "video_core/surface.h" | 8 | #include "video_core/surface.h" |
| 10 | #include "video_core/texture_cache/formatter.h" | 9 | #include "video_core/texture_cache/formatter.h" |
| @@ -26,8 +25,7 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i | |||
| 26 | ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false, true), | 25 | ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false, true), |
| 27 | "Image view format {} is incompatible with image format {}", info.format, | 26 | "Image view format {} is incompatible with image format {}", info.format, |
| 28 | image_info.format); | 27 | image_info.format); |
| 29 | const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 28 | if (image_info.forced_flushed) { |
| 30 | if (image_info.type == ImageType::Linear && is_async) { | ||
| 31 | flags |= ImageViewFlagBits::PreemtiveDownload; | 29 | flags |= ImageViewFlagBits::PreemtiveDownload; |
| 32 | } | 30 | } |
| 33 | if (image_info.type == ImageType::e3D && info.type != ImageViewType::e3D) { | 31 | if (image_info.type == ImageType::e3D && info.type != ImageViewType::e3D) { |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b5297e76b..e1198dcf8 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -491,6 +491,32 @@ void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) { | |||
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | template <class P> | 493 | template <class P> |
| 494 | std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(VAddr cpu_addr, | ||
| 495 | u64 size) { | ||
| 496 | std::optional<VideoCore::RasterizerDownloadArea> area{}; | ||
| 497 | ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) { | ||
| 498 | if (False(image.flags & ImageFlagBits::GpuModified)) { | ||
| 499 | return; | ||
| 500 | } | ||
| 501 | if (!area) { | ||
| 502 | area.emplace(); | ||
| 503 | area->start_address = cpu_addr; | ||
| 504 | area->end_address = cpu_addr + size; | ||
| 505 | area->preemtive = true; | ||
| 506 | } | ||
| 507 | area->start_address = std::min(area->start_address, image.cpu_addr); | ||
| 508 | area->end_address = std::max(area->end_address, image.cpu_addr_end); | ||
| 509 | for (auto image_view_id : image.image_view_ids) { | ||
| 510 | auto& image_view = slot_image_views[image_view_id]; | ||
| 511 | image_view.flags |= ImageViewFlagBits::PreemtiveDownload; | ||
| 512 | } | ||
| 513 | area->preemtive &= image.info.forced_flushed; | ||
| 514 | image.info.forced_flushed = true; | ||
| 515 | }); | ||
| 516 | return area; | ||
| 517 | } | ||
| 518 | |||
| 519 | template <class P> | ||
| 494 | void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | 520 | void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { |
| 495 | std::vector<ImageId> deleted_images; | 521 | std::vector<ImageId> deleted_images; |
| 496 | ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); | 522 | ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); |
| @@ -683,6 +709,7 @@ void TextureCache<P>::CommitAsyncFlushes() { | |||
| 683 | download_info.async_buffer_id = last_async_buffer_id; | 709 | download_info.async_buffer_id = last_async_buffer_id; |
| 684 | } | 710 | } |
| 685 | } | 711 | } |
| 712 | |||
| 686 | if (any_none_dma) { | 713 | if (any_none_dma) { |
| 687 | auto download_map = runtime.DownloadStagingBuffer(total_size_bytes, true); | 714 | auto download_map = runtime.DownloadStagingBuffer(total_size_bytes, true); |
| 688 | for (const PendingDownload& download_info : download_ids) { | 715 | for (const PendingDownload& download_info : download_ids) { |
| @@ -695,6 +722,7 @@ void TextureCache<P>::CommitAsyncFlushes() { | |||
| 695 | } | 722 | } |
| 696 | uncommitted_async_buffers.emplace_back(download_map); | 723 | uncommitted_async_buffers.emplace_back(download_map); |
| 697 | } | 724 | } |
| 725 | |||
| 698 | async_buffers.emplace_back(std::move(uncommitted_async_buffers)); | 726 | async_buffers.emplace_back(std::move(uncommitted_async_buffers)); |
| 699 | uncommitted_async_buffers.clear(); | 727 | uncommitted_async_buffers.clear(); |
| 700 | } | 728 | } |
| @@ -783,17 +811,22 @@ void TextureCache<P>::PopAsyncFlushes() { | |||
| 783 | } | 811 | } |
| 784 | 812 | ||
| 785 | template <class P> | 813 | template <class P> |
| 786 | ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand) { | 814 | ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload) { |
| 787 | const ImageInfo dst_info(operand); | 815 | const ImageInfo dst_info(operand); |
| 788 | const ImageId dst_id = FindDMAImage(dst_info, operand.address); | 816 | const ImageId dst_id = FindDMAImage(dst_info, operand.address); |
| 789 | if (!dst_id) { | 817 | if (!dst_id) { |
| 790 | return NULL_IMAGE_ID; | 818 | return NULL_IMAGE_ID; |
| 791 | } | 819 | } |
| 792 | const auto& image = slot_images[dst_id]; | 820 | auto& image = slot_images[dst_id]; |
| 793 | if (False(image.flags & ImageFlagBits::GpuModified)) { | 821 | if (False(image.flags & ImageFlagBits::GpuModified)) { |
| 794 | // No need to waste time on an image that's synced with guest | 822 | // No need to waste time on an image that's synced with guest |
| 795 | return NULL_IMAGE_ID; | 823 | return NULL_IMAGE_ID; |
| 796 | } | 824 | } |
| 825 | if (!is_upload && !image.info.dma_downloaded) { | ||
| 826 | // Force a full sync. | ||
| 827 | image.info.dma_downloaded = true; | ||
| 828 | return NULL_IMAGE_ID; | ||
| 829 | } | ||
| 797 | const auto base = image.TryFindBase(operand.address); | 830 | const auto base = image.TryFindBase(operand.address); |
| 798 | if (!base) { | 831 | if (!base) { |
| 799 | return NULL_IMAGE_ID; | 832 | return NULL_IMAGE_ID; |
| @@ -1290,7 +1323,6 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 1290 | all_siblings.push_back(overlap_id); | 1323 | all_siblings.push_back(overlap_id); |
| 1291 | } else { | 1324 | } else { |
| 1292 | bad_overlap_ids.push_back(overlap_id); | 1325 | bad_overlap_ids.push_back(overlap_id); |
| 1293 | overlap.flags |= ImageFlagBits::BadOverlap; | ||
| 1294 | } | 1326 | } |
| 1295 | }; | 1327 | }; |
| 1296 | ForEachImageInRegion(cpu_addr, size_bytes, region_check); | 1328 | ForEachImageInRegion(cpu_addr, size_bytes, region_check); |
| @@ -1401,7 +1433,12 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 1401 | ImageBase& aliased = slot_images[aliased_id]; | 1433 | ImageBase& aliased = slot_images[aliased_id]; |
| 1402 | aliased.overlapping_images.push_back(new_image_id); | 1434 | aliased.overlapping_images.push_back(new_image_id); |
| 1403 | new_image.overlapping_images.push_back(aliased_id); | 1435 | new_image.overlapping_images.push_back(aliased_id); |
| 1404 | new_image.flags |= ImageFlagBits::BadOverlap; | 1436 | if (aliased.info.resources.levels == 1 && aliased.overlapping_images.size() > 1) { |
| 1437 | aliased.flags |= ImageFlagBits::BadOverlap; | ||
| 1438 | } | ||
| 1439 | if (new_image.info.resources.levels == 1 && new_image.overlapping_images.size() > 1) { | ||
| 1440 | new_image.flags |= ImageFlagBits::BadOverlap; | ||
| 1441 | } | ||
| 1405 | } | 1442 | } |
| 1406 | RegisterImage(new_image_id); | 1443 | RegisterImage(new_image_id); |
| 1407 | return new_image_id; | 1444 | return new_image_id; |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 758b7e212..0720494e5 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -179,6 +179,8 @@ public: | |||
| 179 | /// Download contents of host images to guest memory in a region | 179 | /// Download contents of host images to guest memory in a region |
| 180 | void DownloadMemory(VAddr cpu_addr, size_t size); | 180 | void DownloadMemory(VAddr cpu_addr, size_t size); |
| 181 | 181 | ||
| 182 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); | ||
| 183 | |||
| 182 | /// Remove images in a region | 184 | /// Remove images in a region |
| 183 | void UnmapMemory(VAddr cpu_addr, size_t size); | 185 | void UnmapMemory(VAddr cpu_addr, size_t size); |
| 184 | 186 | ||
| @@ -205,7 +207,7 @@ public: | |||
| 205 | /// Pop asynchronous downloads | 207 | /// Pop asynchronous downloads |
| 206 | void PopAsyncFlushes(); | 208 | void PopAsyncFlushes(); |
| 207 | 209 | ||
| 208 | [[nodiscard]] ImageId DmaImageId(const Tegra::DMA::ImageOperand& operand); | 210 | [[nodiscard]] ImageId DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload); |
| 209 | 211 | ||
| 210 | [[nodiscard]] std::pair<Image*, BufferImageCopy> DmaBufferImageCopy( | 212 | [[nodiscard]] std::pair<Image*, BufferImageCopy> DmaBufferImageCopy( |
| 211 | const Tegra::DMA::ImageCopy& copy_info, const Tegra::DMA::BufferOperand& buffer_operand, | 213 | const Tegra::DMA::ImageCopy& copy_info, const Tegra::DMA::BufferOperand& buffer_operand, |