summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2021-07-18 18:40:14 +0200
committerGravatar Fernando Sahmkow2021-11-16 22:11:27 +0100
commit22f4b290b6f0894d29302102f539dd8753961f04 (patch)
treed0777996569139bb07a152bedd03509951da0402 /src/video_core/texture_cache
parentMerge pull request #7326 from ameerj/vp8 (diff)
downloadyuzu-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.h4
-rw-r--r--src/video_core/texture_cache/image_info.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h113
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h10
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};
37DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) 41DECLARE_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;
15using VideoCore::Surface::PixelFormat; 15using VideoCore::Surface::PixelFormat;
16 16
17struct ImageInfo { 17struct 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
626template <class P> 673template <class P>
674bool 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
698template <class P>
627ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, 699ImageId 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;