diff options
| author | 2021-07-18 18:40:14 +0200 | |
|---|---|---|
| committer | 2021-11-16 22:11:27 +0100 | |
| commit | 22f4b290b6f0894d29302102f539dd8753961f04 (patch) | |
| tree | d0777996569139bb07a152bedd03509951da0402 /src/video_core/texture_cache | |
| parent | Merge pull request #7326 from ameerj/vp8 (diff) | |
| download | yuzu-22f4b290b6f0894d29302102f539dd8753961f04.tar.gz yuzu-22f4b290b6f0894d29302102f539dd8753961f04.tar.xz yuzu-22f4b290b6f0894d29302102f539dd8753961f04.zip | |
VideoCore: Initial Setup for the Resolution Scaler.
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/image_base.h | 4 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_info.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 113 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 10 |
4 files changed, 126 insertions, 3 deletions
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 0c17a791b..1cd30fd37 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h | |||
| @@ -33,6 +33,10 @@ enum class ImageFlagBits : u32 { | |||
| 33 | ///< garbage collection priority | 33 | ///< garbage collection priority |
| 34 | Alias = 1 << 11, ///< This image has aliases and has priority on garbage | 34 | Alias = 1 << 11, ///< This image has aliases and has priority on garbage |
| 35 | ///< collection | 35 | ///< collection |
| 36 | |||
| 37 | // Rescaler | ||
| 38 | Rescaled = 1 << 12, | ||
| 39 | RescaleChecked = 1 << 13, | ||
| 36 | }; | 40 | }; |
| 37 | DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) | 41 | DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) |
| 38 | 42 | ||
diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 5049fc36e..16d4cee37 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h | |||
| @@ -15,7 +15,7 @@ using Tegra::Texture::TICEntry; | |||
| 15 | using VideoCore::Surface::PixelFormat; | 15 | using VideoCore::Surface::PixelFormat; |
| 16 | 16 | ||
| 17 | struct ImageInfo { | 17 | struct ImageInfo { |
| 18 | explicit ImageInfo() = default; | 18 | ImageInfo() = default; |
| 19 | explicit ImageInfo(const TICEntry& config) noexcept; | 19 | explicit ImageInfo(const TICEntry& config) noexcept; |
| 20 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept; | 20 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept; |
| 21 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept; | 21 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index f70c1f764..560da4f16 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -35,6 +35,7 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | |||
| 35 | Tegra::MemoryManager& gpu_memory_) | 35 | Tegra::MemoryManager& gpu_memory_) |
| 36 | : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, | 36 | : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, |
| 37 | kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { | 37 | kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { |
| 38 | runtime.Init(); | ||
| 38 | // Configure null sampler | 39 | // Configure null sampler |
| 39 | TSCEntry sampler_descriptor{}; | 40 | TSCEntry sampler_descriptor{}; |
| 40 | sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); | 41 | sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); |
| @@ -103,6 +104,7 @@ void TextureCache<P>::TickFrame() { | |||
| 103 | sentenced_images.Tick(); | 104 | sentenced_images.Tick(); |
| 104 | sentenced_framebuffers.Tick(); | 105 | sentenced_framebuffers.Tick(); |
| 105 | sentenced_image_view.Tick(); | 106 | sentenced_image_view.Tick(); |
| 107 | runtime.TickFrame(); | ||
| 106 | ++frame_tick; | 108 | ++frame_tick; |
| 107 | } | 109 | } |
| 108 | 110 | ||
| @@ -208,18 +210,63 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) { | |||
| 208 | const bool force = flags[Dirty::RenderTargetControl]; | 210 | const bool force = flags[Dirty::RenderTargetControl]; |
| 209 | flags[Dirty::RenderTargetControl] = false; | 211 | flags[Dirty::RenderTargetControl] = false; |
| 210 | 212 | ||
| 213 | bool can_rescale = true; | ||
| 214 | std::array<ImageId, NUM_RT> tmp_color_images{}; | ||
| 215 | ImageId tmp_depth_image{}; | ||
| 216 | const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { | ||
| 217 | if (view_id) { | ||
| 218 | const auto& view = slot_image_views[view_id]; | ||
| 219 | const auto image_id = view.image_id; | ||
| 220 | id_save = image_id; | ||
| 221 | auto& image = slot_images[image_id]; | ||
| 222 | can_rescale &= ImageCanRescale(image); | ||
| 223 | } else { | ||
| 224 | id_save = CORRUPT_ID; | ||
| 225 | } | ||
| 226 | }; | ||
| 211 | for (size_t index = 0; index < NUM_RT; ++index) { | 227 | for (size_t index = 0; index < NUM_RT; ++index) { |
| 212 | ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; | 228 | ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; |
| 213 | if (flags[Dirty::ColorBuffer0 + index] || force) { | 229 | if (flags[Dirty::ColorBuffer0 + index] || force) { |
| 214 | flags[Dirty::ColorBuffer0 + index] = false; | 230 | flags[Dirty::ColorBuffer0 + index] = false; |
| 215 | BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); | 231 | BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); |
| 216 | } | 232 | } |
| 217 | PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); | 233 | check_rescale(color_buffer_id, tmp_color_images[index]); |
| 218 | } | 234 | } |
| 219 | if (flags[Dirty::ZetaBuffer] || force) { | 235 | if (flags[Dirty::ZetaBuffer] || force) { |
| 220 | flags[Dirty::ZetaBuffer] = false; | 236 | flags[Dirty::ZetaBuffer] = false; |
| 221 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | 237 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); |
| 222 | } | 238 | } |
| 239 | check_rescale(render_targets.depth_buffer_id, tmp_depth_image); | ||
| 240 | |||
| 241 | if (can_rescale) { | ||
| 242 | const auto scale_up = [this](ImageId image_id) { | ||
| 243 | if (image_id != CORRUPT_ID) { | ||
| 244 | Image& image = slot_images[image_id]; | ||
| 245 | image.ScaleUp(); | ||
| 246 | } | ||
| 247 | }; | ||
| 248 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 249 | scale_up(tmp_color_images[index]); | ||
| 250 | } | ||
| 251 | scale_up(tmp_depth_image); | ||
| 252 | } else { | ||
| 253 | const auto scale_down = [this](ImageId image_id) { | ||
| 254 | if (image_id != CORRUPT_ID) { | ||
| 255 | Image& image = slot_images[image_id]; | ||
| 256 | image.ScaleDown(); | ||
| 257 | } | ||
| 258 | }; | ||
| 259 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 260 | scale_down(tmp_color_images[index]); | ||
| 261 | } | ||
| 262 | scale_down(tmp_depth_image); | ||
| 263 | } | ||
| 264 | // Rescale End | ||
| 265 | |||
| 266 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 267 | ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; | ||
| 268 | PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); | ||
| 269 | } | ||
| 223 | const ImageViewId depth_buffer_id = render_targets.depth_buffer_id; | 270 | const ImageViewId depth_buffer_id = render_targets.depth_buffer_id; |
| 224 | 271 | ||
| 225 | PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); | 272 | PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); |
| @@ -624,6 +671,31 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, | |||
| 624 | } | 671 | } |
| 625 | 672 | ||
| 626 | template <class P> | 673 | template <class P> |
| 674 | bool TextureCache<P>::ImageCanRescale(Image& image) { | ||
| 675 | if (True(image.flags & ImageFlagBits::Rescaled) || | ||
| 676 | True(image.flags & ImageFlagBits::RescaleChecked)) { | ||
| 677 | return true; | ||
| 678 | } | ||
| 679 | const auto& info = image.info; | ||
| 680 | const bool can_this_rescale = | ||
| 681 | (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; | ||
| 682 | if (!can_this_rescale) { | ||
| 683 | image.flags &= ~ImageFlagBits::RescaleChecked; | ||
| 684 | return false; | ||
| 685 | } | ||
| 686 | image.flags |= ImageFlagBits::RescaleChecked; | ||
| 687 | for (const auto& alias : image.aliased_images) { | ||
| 688 | Image& other_image = slot_images[alias.id]; | ||
| 689 | if (!ImageCanRescale(other_image)) { | ||
| 690 | image.flags &= ~ImageFlagBits::RescaleChecked; | ||
| 691 | return false; | ||
| 692 | } | ||
| 693 | } | ||
| 694 | image.flags &= ~ImageFlagBits::RescaleChecked; | ||
| 695 | return true; | ||
| 696 | } | ||
| 697 | |||
| 698 | template <class P> | ||
| 627 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, | 699 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, |
| 628 | RelaxedOptions options) { | 700 | RelaxedOptions options) { |
| 629 | std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); | 701 | std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); |
| @@ -660,12 +732,18 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 660 | std::vector<ImageId> right_aliased_ids; | 732 | std::vector<ImageId> right_aliased_ids; |
| 661 | std::unordered_set<ImageId> ignore_textures; | 733 | std::unordered_set<ImageId> ignore_textures; |
| 662 | std::vector<ImageId> bad_overlap_ids; | 734 | std::vector<ImageId> bad_overlap_ids; |
| 735 | std::vector<ImageId> all_siblings; | ||
| 736 | const bool this_is_linear = info.type == ImageType::Linear; | ||
| 663 | const auto region_check = [&](ImageId overlap_id, ImageBase& overlap) { | 737 | const auto region_check = [&](ImageId overlap_id, ImageBase& overlap) { |
| 664 | if (True(overlap.flags & ImageFlagBits::Remapped)) { | 738 | if (True(overlap.flags & ImageFlagBits::Remapped)) { |
| 665 | ignore_textures.insert(overlap_id); | 739 | ignore_textures.insert(overlap_id); |
| 666 | return; | 740 | return; |
| 667 | } | 741 | } |
| 668 | if (info.type == ImageType::Linear) { | 742 | const bool overlap_is_linear = overlap.info.type == ImageType::Linear; |
| 743 | if (this_is_linear != overlap_is_linear) { | ||
| 744 | return; | ||
| 745 | } | ||
| 746 | if (this_is_linear && overlap_is_linear) { | ||
| 669 | if (info.pitch == overlap.info.pitch && gpu_addr == overlap.gpu_addr) { | 747 | if (info.pitch == overlap.info.pitch && gpu_addr == overlap.gpu_addr) { |
| 670 | // Alias linear images with the same pitch | 748 | // Alias linear images with the same pitch |
| 671 | left_aliased_ids.push_back(overlap_id); | 749 | left_aliased_ids.push_back(overlap_id); |
| @@ -681,6 +759,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 681 | cpu_addr = solution->cpu_addr; | 759 | cpu_addr = solution->cpu_addr; |
| 682 | new_info.resources = solution->resources; | 760 | new_info.resources = solution->resources; |
| 683 | overlap_ids.push_back(overlap_id); | 761 | overlap_ids.push_back(overlap_id); |
| 762 | all_siblings.push_back(overlap_id); | ||
| 684 | return; | 763 | return; |
| 685 | } | 764 | } |
| 686 | static constexpr auto options = RelaxedOptions::Size | RelaxedOptions::Format; | 765 | static constexpr auto options = RelaxedOptions::Size | RelaxedOptions::Format; |
| @@ -688,10 +767,12 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 688 | if (IsSubresource(new_info, overlap, gpu_addr, options, broken_views, native_bgr)) { | 767 | if (IsSubresource(new_info, overlap, gpu_addr, options, broken_views, native_bgr)) { |
| 689 | left_aliased_ids.push_back(overlap_id); | 768 | left_aliased_ids.push_back(overlap_id); |
| 690 | overlap.flags |= ImageFlagBits::Alias; | 769 | overlap.flags |= ImageFlagBits::Alias; |
| 770 | all_siblings.push_back(overlap_id); | ||
| 691 | } else if (IsSubresource(overlap.info, new_image_base, overlap.gpu_addr, options, | 771 | } else if (IsSubresource(overlap.info, new_image_base, overlap.gpu_addr, options, |
| 692 | broken_views, native_bgr)) { | 772 | broken_views, native_bgr)) { |
| 693 | right_aliased_ids.push_back(overlap_id); | 773 | right_aliased_ids.push_back(overlap_id); |
| 694 | overlap.flags |= ImageFlagBits::Alias; | 774 | overlap.flags |= ImageFlagBits::Alias; |
| 775 | all_siblings.push_back(overlap_id); | ||
| 695 | } else { | 776 | } else { |
| 696 | bad_overlap_ids.push_back(overlap_id); | 777 | bad_overlap_ids.push_back(overlap_id); |
| 697 | overlap.flags |= ImageFlagBits::BadOverlap; | 778 | overlap.flags |= ImageFlagBits::BadOverlap; |
| @@ -709,8 +790,36 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 709 | } | 790 | } |
| 710 | }; | 791 | }; |
| 711 | ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); | 792 | ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); |
| 793 | |||
| 794 | bool can_rescale = | ||
| 795 | (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; | ||
| 796 | for (const ImageId sibling_id : all_siblings) { | ||
| 797 | if (!can_rescale) { | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | Image& sibling = slot_images[sibling_id]; | ||
| 801 | can_rescale &= ImageCanRescale(sibling); | ||
| 802 | } | ||
| 803 | |||
| 804 | if (can_rescale) { | ||
| 805 | for (const ImageId sibling_id : all_siblings) { | ||
| 806 | Image& sibling = slot_images[sibling_id]; | ||
| 807 | sibling.ScaleUp(); | ||
| 808 | } | ||
| 809 | } else { | ||
| 810 | for (const ImageId sibling_id : all_siblings) { | ||
| 811 | Image& sibling = slot_images[sibling_id]; | ||
| 812 | sibling.ScaleDown(); | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 712 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); | 816 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); |
| 713 | Image& new_image = slot_images[new_image_id]; | 817 | Image& new_image = slot_images[new_image_id]; |
| 818 | if (can_rescale) { | ||
| 819 | new_image.ScaleUp(); | ||
| 820 | } else { | ||
| 821 | new_image.ScaleDown(); | ||
| 822 | } | ||
| 714 | 823 | ||
| 715 | if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { | 824 | if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { |
| 716 | new_image.flags |= ImageFlagBits::Sparse; | 825 | new_image.flags |= ImageFlagBits::Sparse; |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 2d1893c1c..a4a2c0832 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -142,6 +142,14 @@ public: | |||
| 142 | const Tegra::Engines::Fermi2D::Surface& src, | 142 | const Tegra::Engines::Fermi2D::Surface& src, |
| 143 | const Tegra::Engines::Fermi2D::Config& copy); | 143 | const Tegra::Engines::Fermi2D::Config& copy); |
| 144 | 144 | ||
| 145 | /// Invalidate the contents of the color buffer index | ||
| 146 | /// These contents become unspecified, the cache can assume aggressive optimizations. | ||
| 147 | void InvalidateColorBuffer(size_t index); | ||
| 148 | |||
| 149 | /// Invalidate the contents of the depth buffer | ||
| 150 | /// These contents become unspecified, the cache can assume aggressive optimizations. | ||
| 151 | void InvalidateDepthBuffer(); | ||
| 152 | |||
| 145 | /// Try to find a cached image view in the given CPU address | 153 | /// Try to find a cached image view in the given CPU address |
| 146 | [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr); | 154 | [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr); |
| 147 | 155 | ||
| @@ -318,6 +326,8 @@ private: | |||
| 318 | /// Returns true if the current clear parameters clear the whole image of a given image view | 326 | /// Returns true if the current clear parameters clear the whole image of a given image view |
| 319 | [[nodiscard]] bool IsFullClear(ImageViewId id); | 327 | [[nodiscard]] bool IsFullClear(ImageViewId id); |
| 320 | 328 | ||
| 329 | bool ImageCanRescale(Image& image); | ||
| 330 | |||
| 321 | Runtime& runtime; | 331 | Runtime& runtime; |
| 322 | VideoCore::RasterizerInterface& rasterizer; | 332 | VideoCore::RasterizerInterface& rasterizer; |
| 323 | Tegra::Engines::Maxwell3D& maxwell3d; | 333 | Tegra::Engines::Maxwell3D& maxwell3d; |