diff options
| author | liamwhite <liamwhite@users.noreply.github.com> | 2023-05-07 19:05:56 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-07 19:05:56 -0400 |
| commit | 2688fb1aa2d80fc4edac87ff93365f3570cd3af8 (patch) | |
| tree | b874061d30aa6a03fd3c92116df92ed6d3b91a19 /src/video_core/texture_cache | |
| parent | e58090c9c731701662d0824c2fd081467f21f5c3 (diff) | |
| parent | 8014dd82594dbb40e13749203e67b21e8447733c (diff) | |
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 @@ #include <fmt/format.h> #include "common/assert.h" +#include "common/settings.h" #include "video_core/surface.h" #include "video_core/texture_cache/format_lookup_table.h" #include "video_core/texture_cache/image_info.h" @@ -22,6 +23,8 @@ using VideoCore::Surface::PixelFormat; using VideoCore::Surface::SurfaceType; ImageInfo::ImageInfo(const TICEntry& config) noexcept { + forced_flushed = config.IsPitchLinear() && !Settings::values.use_reactive_flushing.GetValue(); + dma_downloaded = forced_flushed; format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type, config.a_type, config.srgb_conversion); num_samples = NumSamples(config.msaa_mode); @@ -117,6 +120,9 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { ImageInfo::ImageInfo(const Maxwell3D::Regs::RenderTargetConfig& ct, Tegra::Texture::MsaaMode msaa_mode) noexcept { + forced_flushed = + ct.tile_mode.is_pitch_linear && !Settings::values.use_reactive_flushing.GetValue(); + dma_downloaded = forced_flushed; format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(ct.format); rescaleable = false; if (ct.tile_mode.is_pitch_linear) { @@ -155,6 +161,9 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs::RenderTargetConfig& ct, ImageInfo::ImageInfo(const Maxwell3D::Regs::Zeta& zt, const Maxwell3D::Regs::ZetaSize& zt_size, Tegra::Texture::MsaaMode msaa_mode) noexcept { + forced_flushed = + zt.tile_mode.is_pitch_linear && !Settings::values.use_reactive_flushing.GetValue(); + dma_downloaded = forced_flushed; format = VideoCore::Surface::PixelFormatFromDepthFormat(zt.format); size.width = zt_size.width; size.height = zt_size.height; @@ -195,6 +204,9 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs::Zeta& zt, const Maxwell3D::Regs::Zet ImageInfo::ImageInfo(const Fermi2D::Surface& config) noexcept { UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero"); + forced_flushed = config.linear == Fermi2D::MemoryLayout::Pitch && + !Settings::values.use_reactive_flushing.GetValue(); + dma_downloaded = forced_flushed; format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format); rescaleable = false; 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 { u32 tile_width_spacing = 0; bool rescaleable = false; bool downscaleable = false; + bool forced_flushed = false; + bool dma_downloaded = false; }; } // 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 @@ #include <algorithm> #include "common/assert.h" -#include "common/settings.h" #include "video_core/compatible_formats.h" #include "video_core/surface.h" #include "video_core/texture_cache/formatter.h" @@ -26,8 +25,7 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false, true), "Image view format {} is incompatible with image format {}", info.format, image_info.format); - const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); - if (image_info.type == ImageType::Linear && is_async) { + if (image_info.forced_flushed) { flags |= ImageViewFlagBits::PreemtiveDownload; } 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) { } template <class P> +std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(VAddr cpu_addr, + u64 size) { + std::optional<VideoCore::RasterizerDownloadArea> area{}; + ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) { + if (False(image.flags & ImageFlagBits::GpuModified)) { + return; + } + if (!area) { + area.emplace(); + area->start_address = cpu_addr; + area->end_address = cpu_addr + size; + area->preemtive = true; + } + area->start_address = std::min(area->start_address, image.cpu_addr); + area->end_address = std::max(area->end_address, image.cpu_addr_end); + for (auto image_view_id : image.image_view_ids) { + auto& image_view = slot_image_views[image_view_id]; + image_view.flags |= ImageViewFlagBits::PreemtiveDownload; + } + area->preemtive &= image.info.forced_flushed; + image.info.forced_flushed = true; + }); + return area; +} + +template <class P> void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { std::vector<ImageId> deleted_images; ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); @@ -683,6 +709,7 @@ void TextureCache<P>::CommitAsyncFlushes() { download_info.async_buffer_id = last_async_buffer_id; } } + if (any_none_dma) { auto download_map = runtime.DownloadStagingBuffer(total_size_bytes, true); for (const PendingDownload& download_info : download_ids) { @@ -695,6 +722,7 @@ void TextureCache<P>::CommitAsyncFlushes() { } uncommitted_async_buffers.emplace_back(download_map); } + async_buffers.emplace_back(std::move(uncommitted_async_buffers)); uncommitted_async_buffers.clear(); } @@ -783,17 +811,22 @@ void TextureCache<P>::PopAsyncFlushes() { } template <class P> -ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand) { +ImageId TextureCache<P>::DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload) { const ImageInfo dst_info(operand); const ImageId dst_id = FindDMAImage(dst_info, operand.address); if (!dst_id) { return NULL_IMAGE_ID; } - const auto& image = slot_images[dst_id]; + auto& image = slot_images[dst_id]; if (False(image.flags & ImageFlagBits::GpuModified)) { // No need to waste time on an image that's synced with guest return NULL_IMAGE_ID; } + if (!is_upload && !image.info.dma_downloaded) { + // Force a full sync. + image.info.dma_downloaded = true; + return NULL_IMAGE_ID; + } const auto base = image.TryFindBase(operand.address); if (!base) { return NULL_IMAGE_ID; @@ -1290,7 +1323,6 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA all_siblings.push_back(overlap_id); } else { bad_overlap_ids.push_back(overlap_id); - overlap.flags |= ImageFlagBits::BadOverlap; } }; ForEachImageInRegion(cpu_addr, size_bytes, region_check); @@ -1401,7 +1433,12 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA ImageBase& aliased = slot_images[aliased_id]; aliased.overlapping_images.push_back(new_image_id); new_image.overlapping_images.push_back(aliased_id); - new_image.flags |= ImageFlagBits::BadOverlap; + if (aliased.info.resources.levels == 1 && aliased.overlapping_images.size() > 1) { + aliased.flags |= ImageFlagBits::BadOverlap; + } + if (new_image.info.resources.levels == 1 && new_image.overlapping_images.size() > 1) { + new_image.flags |= ImageFlagBits::BadOverlap; + } } RegisterImage(new_image_id); 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: /// Download contents of host images to guest memory in a region void DownloadMemory(VAddr cpu_addr, size_t size); + std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); + /// Remove images in a region void UnmapMemory(VAddr cpu_addr, size_t size); @@ -205,7 +207,7 @@ public: /// Pop asynchronous downloads void PopAsyncFlushes(); - [[nodiscard]] ImageId DmaImageId(const Tegra::DMA::ImageOperand& operand); + [[nodiscard]] ImageId DmaImageId(const Tegra::DMA::ImageOperand& operand, bool is_upload); [[nodiscard]] std::pair<Image*, BufferImageCopy> DmaBufferImageCopy( const Tegra::DMA::ImageCopy& copy_info, const Tegra::DMA::BufferOperand& buffer_operand, |
