diff options
| author | 2021-07-19 04:32:03 +0200 | |
|---|---|---|
| committer | 2021-11-16 22:11:27 +0100 | |
| commit | ba18047e8d06584de0ce18cdbb303a6d9a8742aa (patch) | |
| tree | 1c7c3cd54bc82de9d7a746ba1172f1fd013ab9b7 /src/video_core/texture_cache | |
| parent | ShaderDecompiler: Add initial support for rescaling. (diff) | |
| download | yuzu-ba18047e8d06584de0ce18cdbb303a6d9a8742aa.tar.gz yuzu-ba18047e8d06584de0ce18cdbb303a6d9a8742aa.tar.xz yuzu-ba18047e8d06584de0ce18cdbb303a6d9a8742aa.zip | |
Texture Cache: Implement Vulkan UpScaling & DownScaling
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/image_info.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 84 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 3 |
3 files changed, 77 insertions, 13 deletions
diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 64fd7010a..022ca9033 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp | |||
| @@ -41,6 +41,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { | |||
| 41 | ASSERT(config.BaseLayer() == 0); | 41 | ASSERT(config.BaseLayer() == 0); |
| 42 | type = ImageType::e1D; | 42 | type = ImageType::e1D; |
| 43 | size.width = config.Width(); | 43 | size.width = config.Width(); |
| 44 | resources.layers = 1; | ||
| 44 | break; | 45 | break; |
| 45 | case TextureType::Texture1DArray: | 46 | case TextureType::Texture1DArray: |
| 46 | UNIMPLEMENTED_IF(config.BaseLayer() != 0); | 47 | UNIMPLEMENTED_IF(config.BaseLayer() != 0); |
| @@ -82,10 +83,12 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { | |||
| 82 | size.width = config.Width(); | 83 | size.width = config.Width(); |
| 83 | size.height = config.Height(); | 84 | size.height = config.Height(); |
| 84 | size.depth = config.Depth(); | 85 | size.depth = config.Depth(); |
| 86 | resources.layers = 1; | ||
| 85 | break; | 87 | break; |
| 86 | case TextureType::Texture1DBuffer: | 88 | case TextureType::Texture1DBuffer: |
| 87 | type = ImageType::Buffer; | 89 | type = ImageType::Buffer; |
| 88 | size.width = config.Width(); | 90 | size.width = config.Width(); |
| 91 | resources.layers = 1; | ||
| 89 | break; | 92 | break; |
| 90 | default: | 93 | default: |
| 91 | UNREACHABLE_MSG("Invalid texture_type={}", static_cast<int>(config.texture_type.Value())); | 94 | UNREACHABLE_MSG("Invalid texture_type={}", static_cast<int>(config.texture_type.Value())); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 560da4f16..95a9e8fe9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -242,24 +242,36 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) { | |||
| 242 | const auto scale_up = [this](ImageId image_id) { | 242 | const auto scale_up = [this](ImageId image_id) { |
| 243 | if (image_id != CORRUPT_ID) { | 243 | if (image_id != CORRUPT_ID) { |
| 244 | Image& image = slot_images[image_id]; | 244 | Image& image = slot_images[image_id]; |
| 245 | image.ScaleUp(); | 245 | return ScaleUp(image); |
| 246 | } | 246 | } |
| 247 | return false; | ||
| 247 | }; | 248 | }; |
| 248 | for (size_t index = 0; index < NUM_RT; ++index) { | 249 | for (size_t index = 0; index < NUM_RT; ++index) { |
| 249 | scale_up(tmp_color_images[index]); | 250 | if (scale_up(tmp_color_images[index])) { |
| 251 | BindRenderTarget(&render_targets.color_buffer_ids[index], | ||
| 252 | FindColorBuffer(index, is_clear)); | ||
| 253 | } | ||
| 254 | } | ||
| 255 | if (scale_up(tmp_depth_image)) { | ||
| 256 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | ||
| 250 | } | 257 | } |
| 251 | scale_up(tmp_depth_image); | ||
| 252 | } else { | 258 | } else { |
| 253 | const auto scale_down = [this](ImageId image_id) { | 259 | const auto scale_down = [this](ImageId image_id) { |
| 254 | if (image_id != CORRUPT_ID) { | 260 | if (image_id != CORRUPT_ID) { |
| 255 | Image& image = slot_images[image_id]; | 261 | Image& image = slot_images[image_id]; |
| 256 | image.ScaleDown(); | 262 | return ScaleDown(image); |
| 257 | } | 263 | } |
| 264 | return false; | ||
| 258 | }; | 265 | }; |
| 259 | for (size_t index = 0; index < NUM_RT; ++index) { | 266 | for (size_t index = 0; index < NUM_RT; ++index) { |
| 260 | scale_down(tmp_color_images[index]); | 267 | if (scale_down(tmp_color_images[index])) { |
| 268 | BindRenderTarget(&render_targets.color_buffer_ids[index], | ||
| 269 | FindColorBuffer(index, is_clear)); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | if (scale_down(tmp_depth_image)) { | ||
| 273 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | ||
| 261 | } | 274 | } |
| 262 | scale_down(tmp_depth_image); | ||
| 263 | } | 275 | } |
| 264 | // Rescale End | 276 | // Rescale End |
| 265 | 277 | ||
| @@ -696,6 +708,47 @@ bool TextureCache<P>::ImageCanRescale(Image& image) { | |||
| 696 | } | 708 | } |
| 697 | 709 | ||
| 698 | template <class P> | 710 | template <class P> |
| 711 | void TextureCache<P>::InvalidateScale(Image& image, bool invalidate_rt) { | ||
| 712 | const std::span<const ImageViewId> image_view_ids = image.image_view_ids; | ||
| 713 | if (invalidate_rt) { | ||
| 714 | auto& dirty = maxwell3d.dirty.flags; | ||
| 715 | dirty[Dirty::RenderTargets] = true; | ||
| 716 | dirty[Dirty::ZetaBuffer] = true; | ||
| 717 | for (size_t rt = 0; rt < NUM_RT; ++rt) { | ||
| 718 | dirty[Dirty::ColorBuffer0 + rt] = true; | ||
| 719 | } | ||
| 720 | for (const ImageViewId image_view_id : image_view_ids) { | ||
| 721 | std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); | ||
| 722 | if (render_targets.depth_buffer_id == image_view_id) { | ||
| 723 | render_targets.depth_buffer_id = ImageViewId{}; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | } | ||
| 727 | RemoveImageViewReferences(image_view_ids); | ||
| 728 | RemoveFramebuffers(image_view_ids); | ||
| 729 | } | ||
| 730 | |||
| 731 | template <class P> | ||
| 732 | bool TextureCache<P>::ScaleUp(Image& image, bool invalidate_rt) { | ||
| 733 | const bool rescaled = image.ScaleUp(); | ||
| 734 | if (!rescaled) { | ||
| 735 | return false; | ||
| 736 | } | ||
| 737 | InvalidateScale(image, invalidate_rt); | ||
| 738 | return true; | ||
| 739 | } | ||
| 740 | |||
| 741 | template <class P> | ||
| 742 | bool TextureCache<P>::ScaleDown(Image& image, bool invalidate_rt) { | ||
| 743 | const bool rescaled = image.ScaleDown(); | ||
| 744 | if (!rescaled) { | ||
| 745 | return false; | ||
| 746 | } | ||
| 747 | InvalidateScale(image, invalidate_rt); | ||
| 748 | return true; | ||
| 749 | } | ||
| 750 | |||
| 751 | template <class P> | ||
| 699 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, | 752 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, |
| 700 | RelaxedOptions options) { | 753 | RelaxedOptions options) { |
| 701 | std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); | 754 | std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); |
| @@ -793,33 +846,32 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 793 | 846 | ||
| 794 | bool can_rescale = | 847 | bool can_rescale = |
| 795 | (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; | 848 | (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; |
| 849 | bool any_rescaled = false; | ||
| 796 | for (const ImageId sibling_id : all_siblings) { | 850 | for (const ImageId sibling_id : all_siblings) { |
| 797 | if (!can_rescale) { | 851 | if (!can_rescale) { |
| 798 | break; | 852 | break; |
| 799 | } | 853 | } |
| 800 | Image& sibling = slot_images[sibling_id]; | 854 | Image& sibling = slot_images[sibling_id]; |
| 801 | can_rescale &= ImageCanRescale(sibling); | 855 | can_rescale &= ImageCanRescale(sibling); |
| 856 | any_rescaled |= True(sibling.flags & ImageFlagBits::Rescaled); | ||
| 802 | } | 857 | } |
| 803 | 858 | ||
| 859 | can_rescale &= any_rescaled; | ||
| 860 | |||
| 804 | if (can_rescale) { | 861 | if (can_rescale) { |
| 805 | for (const ImageId sibling_id : all_siblings) { | 862 | for (const ImageId sibling_id : all_siblings) { |
| 806 | Image& sibling = slot_images[sibling_id]; | 863 | Image& sibling = slot_images[sibling_id]; |
| 807 | sibling.ScaleUp(); | 864 | ScaleUp(sibling, true); |
| 808 | } | 865 | } |
| 809 | } else { | 866 | } else { |
| 810 | for (const ImageId sibling_id : all_siblings) { | 867 | for (const ImageId sibling_id : all_siblings) { |
| 811 | Image& sibling = slot_images[sibling_id]; | 868 | Image& sibling = slot_images[sibling_id]; |
| 812 | sibling.ScaleDown(); | 869 | ScaleDown(sibling, true); |
| 813 | } | 870 | } |
| 814 | } | 871 | } |
| 815 | 872 | ||
| 816 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); | 873 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); |
| 817 | Image& new_image = slot_images[new_image_id]; | 874 | Image& new_image = slot_images[new_image_id]; |
| 818 | if (can_rescale) { | ||
| 819 | new_image.ScaleUp(); | ||
| 820 | } else { | ||
| 821 | new_image.ScaleDown(); | ||
| 822 | } | ||
| 823 | 875 | ||
| 824 | if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { | 876 | if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { |
| 825 | new_image.flags |= ImageFlagBits::Sparse; | 877 | new_image.flags |= ImageFlagBits::Sparse; |
| @@ -840,6 +892,12 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 840 | // TODO: Only upload what we need | 892 | // TODO: Only upload what we need |
| 841 | RefreshContents(new_image, new_image_id); | 893 | RefreshContents(new_image, new_image_id); |
| 842 | 894 | ||
| 895 | if (can_rescale) { | ||
| 896 | new_image.ScaleUp(); | ||
| 897 | } else { | ||
| 898 | new_image.ScaleDown(); | ||
| 899 | } | ||
| 900 | |||
| 843 | for (const ImageId overlap_id : overlap_ids) { | 901 | for (const ImageId overlap_id : overlap_ids) { |
| 844 | Image& overlap = slot_images[overlap_id]; | 902 | Image& overlap = slot_images[overlap_id]; |
| 845 | if (overlap.info.num_samples != new_image.info.num_samples) { | 903 | if (overlap.info.num_samples != new_image.info.num_samples) { |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index a4a2c0832..042678786 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -327,6 +327,9 @@ private: | |||
| 327 | [[nodiscard]] bool IsFullClear(ImageViewId id); | 327 | [[nodiscard]] bool IsFullClear(ImageViewId id); |
| 328 | 328 | ||
| 329 | bool ImageCanRescale(Image& image); | 329 | bool ImageCanRescale(Image& image); |
| 330 | void InvalidateScale(Image& image, bool invalidate_rt = false); | ||
| 331 | bool ScaleUp(Image& image, bool invalidate_rt = false); | ||
| 332 | bool ScaleDown(Image& image, bool invalidate_rt = false); | ||
| 330 | 333 | ||
| 331 | Runtime& runtime; | 334 | Runtime& runtime; |
| 332 | VideoCore::RasterizerInterface& rasterizer; | 335 | VideoCore::RasterizerInterface& rasterizer; |