diff options
| author | 2021-07-20 07:40:05 +0200 | |
|---|---|---|
| committer | 2021-11-16 22:11:27 +0100 | |
| commit | 84f2aea8962146be899131b032fcdf9b4e1f6ddf (patch) | |
| tree | d6db3d9be0e24c045ef39fe0f53b8b6f6da0cfef /src | |
| parent | gl_texture_cache: WIP texture rescale (diff) | |
| download | yuzu-84f2aea8962146be899131b032fcdf9b4e1f6ddf.tar.gz yuzu-84f2aea8962146be899131b032fcdf9b4e1f6ddf.tar.xz yuzu-84f2aea8962146be899131b032fcdf9b4e1f6ddf.zip | |
Texture Cache: More rescaling fixes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 162 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 6 |
4 files changed, 96 insertions, 84 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 9b2a09007..2d9f770cd 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -918,7 +918,7 @@ bool Image::ScaleUp() { | |||
| 918 | return false; | 918 | return false; |
| 919 | } | 919 | } |
| 920 | flags |= ImageFlagBits::Rescaled; | 920 | flags |= ImageFlagBits::Rescaled; |
| 921 | Scale(); | 921 | //Scale(); |
| 922 | return true; | 922 | return true; |
| 923 | } | 923 | } |
| 924 | 924 | ||
| @@ -927,7 +927,7 @@ bool Image::ScaleDown() { | |||
| 927 | return false; | 927 | return false; |
| 928 | } | 928 | } |
| 929 | flags &= ~ImageFlagBits::Rescaled; | 929 | flags &= ~ImageFlagBits::Rescaled; |
| 930 | Scale(); | 930 | //Scale(); |
| 931 | return true; | 931 | return true; |
| 932 | } | 932 | } |
| 933 | 933 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 668554d1e..5fd190825 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -1078,6 +1078,10 @@ bool Image::ScaleUp(bool save_as_backup) { | |||
| 1078 | MemoryCommit new_commit( | 1078 | MemoryCommit new_commit( |
| 1079 | runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal)); | 1079 | runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal)); |
| 1080 | 1080 | ||
| 1081 | if (aspect_mask == 0) { | ||
| 1082 | aspect_mask = ImageAspectMask(info.format); | ||
| 1083 | } | ||
| 1084 | |||
| 1081 | const auto scale_up = [&](u32 value) { | 1085 | const auto scale_up = [&](u32 value) { |
| 1082 | return (value * resolution.up_scale) >> resolution.down_shift; | 1086 | return (value * resolution.up_scale) >> resolution.down_shift; |
| 1083 | }; | 1087 | }; |
| @@ -1170,6 +1174,10 @@ bool Image::ScaleDown(bool save_as_backup) { | |||
| 1170 | return (value * resolution.up_scale) >> resolution.down_shift; | 1174 | return (value * resolution.up_scale) >> resolution.down_shift; |
| 1171 | }; | 1175 | }; |
| 1172 | 1176 | ||
| 1177 | if (aspect_mask == 0) { | ||
| 1178 | aspect_mask = ImageAspectMask(info.format); | ||
| 1179 | } | ||
| 1180 | |||
| 1173 | const bool is_2d = info.type == ImageType::e2D; | 1181 | const bool is_2d = info.type == ImageType::e2D; |
| 1174 | boost::container::small_vector<VkImageBlit, 4> vkRegions(info.resources.levels); | 1182 | boost::container::small_vector<VkImageBlit, 4> vkRegions(info.resources.levels); |
| 1175 | for (s32 level = 0; level < info.resources.levels; level++) { | 1183 | for (s32 level = 0; level < info.resources.levels; level++) { |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 95a9e8fe9..b7d1ae92d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -204,75 +204,68 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) { | |||
| 204 | PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); | 204 | PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); |
| 205 | return; | 205 | return; |
| 206 | } | 206 | } |
| 207 | flags[Dirty::RenderTargets] = false; | ||
| 208 | |||
| 209 | // Render target control is used on all render targets, so force look ups when this one is up | ||
| 210 | const bool force = flags[Dirty::RenderTargetControl]; | ||
| 211 | flags[Dirty::RenderTargetControl] = false; | ||
| 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 | }; | ||
| 227 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 228 | ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; | ||
| 229 | if (flags[Dirty::ColorBuffer0 + index] || force) { | ||
| 230 | flags[Dirty::ColorBuffer0 + index] = false; | ||
| 231 | BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); | ||
| 232 | } | ||
| 233 | check_rescale(color_buffer_id, tmp_color_images[index]); | ||
| 234 | } | ||
| 235 | if (flags[Dirty::ZetaBuffer] || force) { | ||
| 236 | flags[Dirty::ZetaBuffer] = false; | ||
| 237 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | ||
| 238 | } | ||
| 239 | check_rescale(render_targets.depth_buffer_id, tmp_depth_image); | ||
| 240 | 207 | ||
| 241 | if (can_rescale) { | 208 | do { |
| 242 | const auto scale_up = [this](ImageId image_id) { | 209 | flags[Dirty::RenderTargets] = false; |
| 243 | if (image_id != CORRUPT_ID) { | 210 | |
| 244 | Image& image = slot_images[image_id]; | 211 | has_deleted_images = false; |
| 245 | return ScaleUp(image); | 212 | // Render target control is used on all render targets, so force look ups when this one is |
| 213 | // up | ||
| 214 | const bool force = flags[Dirty::RenderTargetControl]; | ||
| 215 | flags[Dirty::RenderTargetControl] = false; | ||
| 216 | |||
| 217 | bool can_rescale = true; | ||
| 218 | std::array<ImageId, NUM_RT> tmp_color_images{}; | ||
| 219 | ImageId tmp_depth_image{}; | ||
| 220 | const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { | ||
| 221 | if (view_id) { | ||
| 222 | const auto& view = slot_image_views[view_id]; | ||
| 223 | const auto image_id = view.image_id; | ||
| 224 | id_save = image_id; | ||
| 225 | auto& image = slot_images[image_id]; | ||
| 226 | can_rescale &= ImageCanRescale(image); | ||
| 227 | } else { | ||
| 228 | id_save = CORRUPT_ID; | ||
| 246 | } | 229 | } |
| 247 | return false; | ||
| 248 | }; | 230 | }; |
| 249 | for (size_t index = 0; index < NUM_RT; ++index) { | 231 | for (size_t index = 0; index < NUM_RT; ++index) { |
| 250 | if (scale_up(tmp_color_images[index])) { | 232 | ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; |
| 251 | BindRenderTarget(&render_targets.color_buffer_ids[index], | 233 | if (flags[Dirty::ColorBuffer0 + index] || force) { |
| 252 | FindColorBuffer(index, is_clear)); | 234 | flags[Dirty::ColorBuffer0 + index] = false; |
| 235 | BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); | ||
| 253 | } | 236 | } |
| 237 | check_rescale(color_buffer_id, tmp_color_images[index]); | ||
| 254 | } | 238 | } |
| 255 | if (scale_up(tmp_depth_image)) { | 239 | if (flags[Dirty::ZetaBuffer] || force) { |
| 240 | flags[Dirty::ZetaBuffer] = false; | ||
| 256 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | 241 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); |
| 257 | } | 242 | } |
| 258 | } else { | 243 | check_rescale(render_targets.depth_buffer_id, tmp_depth_image); |
| 259 | const auto scale_down = [this](ImageId image_id) { | 244 | |
| 260 | if (image_id != CORRUPT_ID) { | 245 | if (can_rescale) { |
| 261 | Image& image = slot_images[image_id]; | 246 | const auto scale_up = [this](ImageId image_id) { |
| 262 | return ScaleDown(image); | 247 | if (image_id != CORRUPT_ID) { |
| 248 | Image& image = slot_images[image_id]; | ||
| 249 | ScaleUp(image); | ||
| 250 | } | ||
| 251 | }; | ||
| 252 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 253 | scale_up(tmp_color_images[index]); | ||
| 263 | } | 254 | } |
| 264 | return false; | 255 | scale_up(tmp_depth_image); |
| 265 | }; | 256 | } else { |
| 266 | for (size_t index = 0; index < NUM_RT; ++index) { | 257 | const auto scale_down = [this](ImageId image_id) { |
| 267 | if (scale_down(tmp_color_images[index])) { | 258 | if (image_id != CORRUPT_ID) { |
| 268 | BindRenderTarget(&render_targets.color_buffer_ids[index], | 259 | Image& image = slot_images[image_id]; |
| 269 | FindColorBuffer(index, is_clear)); | 260 | ScaleDown(image); |
| 261 | } | ||
| 262 | }; | ||
| 263 | for (size_t index = 0; index < NUM_RT; ++index) { | ||
| 264 | scale_down(tmp_color_images[index]); | ||
| 270 | } | 265 | } |
| 266 | scale_down(tmp_depth_image); | ||
| 271 | } | 267 | } |
| 272 | if (scale_down(tmp_depth_image)) { | 268 | } while (has_deleted_images); |
| 273 | BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); | ||
| 274 | } | ||
| 275 | } | ||
| 276 | // Rescale End | 269 | // Rescale End |
| 277 | 270 | ||
| 278 | for (size_t index = 0; index < NUM_RT; ++index) { | 271 | for (size_t index = 0; index < NUM_RT; ++index) { |
| @@ -708,43 +701,54 @@ bool TextureCache<P>::ImageCanRescale(Image& image) { | |||
| 708 | } | 701 | } |
| 709 | 702 | ||
| 710 | template <class P> | 703 | template <class P> |
| 711 | void TextureCache<P>::InvalidateScale(Image& image, bool invalidate_rt) { | 704 | void TextureCache<P>::InvalidateScale(Image& image) { |
| 712 | const std::span<const ImageViewId> image_view_ids = image.image_view_ids; | 705 | const std::span<const ImageViewId> image_view_ids = image.image_view_ids; |
| 713 | if (invalidate_rt) { | 706 | auto& dirty = maxwell3d.dirty.flags; |
| 714 | auto& dirty = maxwell3d.dirty.flags; | 707 | dirty[Dirty::RenderTargets] = true; |
| 715 | dirty[Dirty::RenderTargets] = true; | 708 | dirty[Dirty::ZetaBuffer] = true; |
| 716 | dirty[Dirty::ZetaBuffer] = true; | 709 | for (size_t rt = 0; rt < NUM_RT; ++rt) { |
| 717 | for (size_t rt = 0; rt < NUM_RT; ++rt) { | 710 | dirty[Dirty::ColorBuffer0 + rt] = true; |
| 718 | dirty[Dirty::ColorBuffer0 + rt] = true; | 711 | } |
| 719 | } | 712 | for (const ImageViewId image_view_id : image_view_ids) { |
| 720 | for (const ImageViewId image_view_id : image_view_ids) { | 713 | std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); |
| 721 | std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); | 714 | if (render_targets.depth_buffer_id == image_view_id) { |
| 722 | if (render_targets.depth_buffer_id == image_view_id) { | 715 | render_targets.depth_buffer_id = ImageViewId{}; |
| 723 | render_targets.depth_buffer_id = ImageViewId{}; | ||
| 724 | } | ||
| 725 | } | 716 | } |
| 726 | } | 717 | } |
| 727 | RemoveImageViewReferences(image_view_ids); | 718 | RemoveImageViewReferences(image_view_ids); |
| 728 | RemoveFramebuffers(image_view_ids); | 719 | RemoveFramebuffers(image_view_ids); |
| 720 | for (const ImageViewId image_view_id : image_view_ids) { | ||
| 721 | sentenced_image_view.Push(std::move(slot_image_views[image_view_id])); | ||
| 722 | slot_image_views.erase(image_view_id); | ||
| 723 | } | ||
| 724 | image.image_view_ids.clear(); | ||
| 725 | image.image_view_infos.clear(); | ||
| 726 | if constexpr (ENABLE_VALIDATION) { | ||
| 727 | std::ranges::fill(graphics_image_view_ids, CORRUPT_ID); | ||
| 728 | std::ranges::fill(compute_image_view_ids, CORRUPT_ID); | ||
| 729 | } | ||
| 730 | graphics_image_table.Invalidate(); | ||
| 731 | compute_image_table.Invalidate(); | ||
| 732 | has_deleted_images = true; | ||
| 729 | } | 733 | } |
| 730 | 734 | ||
| 731 | template <class P> | 735 | template <class P> |
| 732 | bool TextureCache<P>::ScaleUp(Image& image, bool invalidate_rt) { | 736 | bool TextureCache<P>::ScaleUp(Image& image) { |
| 733 | const bool rescaled = image.ScaleUp(); | 737 | const bool rescaled = image.ScaleUp(); |
| 734 | if (!rescaled) { | 738 | if (!rescaled) { |
| 735 | return false; | 739 | return false; |
| 736 | } | 740 | } |
| 737 | InvalidateScale(image, invalidate_rt); | 741 | InvalidateScale(image); |
| 738 | return true; | 742 | return true; |
| 739 | } | 743 | } |
| 740 | 744 | ||
| 741 | template <class P> | 745 | template <class P> |
| 742 | bool TextureCache<P>::ScaleDown(Image& image, bool invalidate_rt) { | 746 | bool TextureCache<P>::ScaleDown(Image& image) { |
| 743 | const bool rescaled = image.ScaleDown(); | 747 | const bool rescaled = image.ScaleDown(); |
| 744 | if (!rescaled) { | 748 | if (!rescaled) { |
| 745 | return false; | 749 | return false; |
| 746 | } | 750 | } |
| 747 | InvalidateScale(image, invalidate_rt); | 751 | InvalidateScale(image); |
| 748 | return true; | 752 | return true; |
| 749 | } | 753 | } |
| 750 | 754 | ||
| @@ -861,12 +865,12 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 861 | if (can_rescale) { | 865 | if (can_rescale) { |
| 862 | for (const ImageId sibling_id : all_siblings) { | 866 | for (const ImageId sibling_id : all_siblings) { |
| 863 | Image& sibling = slot_images[sibling_id]; | 867 | Image& sibling = slot_images[sibling_id]; |
| 864 | ScaleUp(sibling, true); | 868 | ScaleUp(sibling); |
| 865 | } | 869 | } |
| 866 | } else { | 870 | } else { |
| 867 | for (const ImageId sibling_id : all_siblings) { | 871 | for (const ImageId sibling_id : all_siblings) { |
| 868 | Image& sibling = slot_images[sibling_id]; | 872 | Image& sibling = slot_images[sibling_id]; |
| 869 | ScaleDown(sibling, true); | 873 | ScaleDown(sibling); |
| 870 | } | 874 | } |
| 871 | } | 875 | } |
| 872 | 876 | ||
| @@ -893,9 +897,9 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA | |||
| 893 | RefreshContents(new_image, new_image_id); | 897 | RefreshContents(new_image, new_image_id); |
| 894 | 898 | ||
| 895 | if (can_rescale) { | 899 | if (can_rescale) { |
| 896 | new_image.ScaleUp(); | 900 | ScaleUp(new_image); |
| 897 | } else { | 901 | } else { |
| 898 | new_image.ScaleDown(); | 902 | ScaleDown(new_image); |
| 899 | } | 903 | } |
| 900 | 904 | ||
| 901 | for (const ImageId overlap_id : overlap_ids) { | 905 | for (const ImageId overlap_id : overlap_ids) { |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 042678786..cdd99242b 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -327,9 +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); | 330 | void InvalidateScale(Image& image); |
| 331 | bool ScaleUp(Image& image, bool invalidate_rt = false); | 331 | bool ScaleUp(Image& image); |
| 332 | bool ScaleDown(Image& image, bool invalidate_rt = false); | 332 | bool ScaleDown(Image& image); |
| 333 | 333 | ||
| 334 | Runtime& runtime; | 334 | Runtime& runtime; |
| 335 | VideoCore::RasterizerInterface& rasterizer; | 335 | VideoCore::RasterizerInterface& rasterizer; |