diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 6 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 104 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 6 |
5 files changed, 91 insertions, 35 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 113528e9b..5d9d370f2 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -354,6 +354,7 @@ struct TextureCacheParams { | |||
| 354 | static constexpr bool FRAMEBUFFER_BLITS = true; | 354 | static constexpr bool FRAMEBUFFER_BLITS = true; |
| 355 | static constexpr bool HAS_EMULATED_COPIES = true; | 355 | static constexpr bool HAS_EMULATED_COPIES = true; |
| 356 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 356 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 357 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = false; | ||
| 357 | 358 | ||
| 358 | using Runtime = OpenGL::TextureCacheRuntime; | 359 | using Runtime = OpenGL::TextureCacheRuntime; |
| 359 | using Image = OpenGL::Image; | 360 | using Image = OpenGL::Image; |
| @@ -361,6 +362,7 @@ struct TextureCacheParams { | |||
| 361 | using ImageView = OpenGL::ImageView; | 362 | using ImageView = OpenGL::ImageView; |
| 362 | using Sampler = OpenGL::Sampler; | 363 | using Sampler = OpenGL::Sampler; |
| 363 | using Framebuffer = OpenGL::Framebuffer; | 364 | using Framebuffer = OpenGL::Framebuffer; |
| 365 | using AsyncBuffer = u32; | ||
| 364 | }; | 366 | }; |
| 365 | 367 | ||
| 366 | using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; | 368 | using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index a65bbeb1c..d39372ec4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -812,8 +812,12 @@ StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size) { | |||
| 812 | return staging_buffer_pool.Request(size, MemoryUsage::Upload); | 812 | return staging_buffer_pool.Request(size, MemoryUsage::Upload); |
| 813 | } | 813 | } |
| 814 | 814 | ||
| 815 | StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | 815 | StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { |
| 816 | return staging_buffer_pool.Request(size, MemoryUsage::Download); | 816 | return staging_buffer_pool.Request(size, MemoryUsage::Download, deferred); |
| 817 | } | ||
| 818 | |||
| 819 | void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) { | ||
| 820 | staging_buffer_pool.FreeDeferred(ref); | ||
| 817 | } | 821 | } |
| 818 | 822 | ||
| 819 | bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) { | 823 | bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) { |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 7ec0df134..1f27a3589 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -51,7 +51,9 @@ public: | |||
| 51 | 51 | ||
| 52 | StagingBufferRef UploadStagingBuffer(size_t size); | 52 | StagingBufferRef UploadStagingBuffer(size_t size); |
| 53 | 53 | ||
| 54 | StagingBufferRef DownloadStagingBuffer(size_t size); | 54 | StagingBufferRef DownloadStagingBuffer(size_t size, bool deferred = false); |
| 55 | |||
| 56 | void FreeDeferredStagingBuffer(StagingBufferRef& ref); | ||
| 55 | 57 | ||
| 56 | void TickFrame(); | 58 | void TickFrame(); |
| 57 | 59 | ||
| @@ -347,6 +349,7 @@ struct TextureCacheParams { | |||
| 347 | static constexpr bool FRAMEBUFFER_BLITS = false; | 349 | static constexpr bool FRAMEBUFFER_BLITS = false; |
| 348 | static constexpr bool HAS_EMULATED_COPIES = false; | 350 | static constexpr bool HAS_EMULATED_COPIES = false; |
| 349 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 351 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 352 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true; | ||
| 350 | 353 | ||
| 351 | using Runtime = Vulkan::TextureCacheRuntime; | 354 | using Runtime = Vulkan::TextureCacheRuntime; |
| 352 | using Image = Vulkan::Image; | 355 | using Image = Vulkan::Image; |
| @@ -354,6 +357,7 @@ struct TextureCacheParams { | |||
| 354 | using ImageView = Vulkan::ImageView; | 357 | using ImageView = Vulkan::ImageView; |
| 355 | using Sampler = Vulkan::Sampler; | 358 | using Sampler = Vulkan::Sampler; |
| 356 | using Framebuffer = Vulkan::Framebuffer; | 359 | using Framebuffer = Vulkan::Framebuffer; |
| 360 | using AsyncBuffer = Vulkan::StagingBufferRef; | ||
| 357 | }; | 361 | }; |
| 358 | 362 | ||
| 359 | using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; | 363 | using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7fe451b5a..87152c8e9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -646,7 +646,28 @@ bool TextureCache<P>::ShouldWaitAsyncFlushes() const noexcept { | |||
| 646 | template <class P> | 646 | template <class P> |
| 647 | void TextureCache<P>::CommitAsyncFlushes() { | 647 | void TextureCache<P>::CommitAsyncFlushes() { |
| 648 | // This is intentionally passing the value by copy | 648 | // This is intentionally passing the value by copy |
| 649 | committed_downloads.push(uncommitted_downloads); | 649 | if constexpr (IMPLEMENTS_ASYNC_DOWNLOADS) { |
| 650 | const std::span<const ImageId> download_ids = uncommitted_downloads; | ||
| 651 | if (download_ids.empty()) { | ||
| 652 | committed_downloads.emplace_back(std::move(uncommitted_downloads)); | ||
| 653 | uncommitted_downloads.clear(); | ||
| 654 | async_buffers.emplace_back(std::optional<AsyncBuffer>{}); | ||
| 655 | return; | ||
| 656 | } | ||
| 657 | size_t total_size_bytes = 0; | ||
| 658 | for (const ImageId image_id : download_ids) { | ||
| 659 | total_size_bytes += slot_images[image_id].unswizzled_size_bytes; | ||
| 660 | } | ||
| 661 | auto download_map = runtime.DownloadStagingBuffer(total_size_bytes, true); | ||
| 662 | for (const ImageId image_id : download_ids) { | ||
| 663 | Image& image = slot_images[image_id]; | ||
| 664 | const auto copies = FullDownloadCopies(image.info); | ||
| 665 | image.DownloadMemory(download_map, copies); | ||
| 666 | download_map.offset += Common::AlignUp(image.unswizzled_size_bytes, 64); | ||
| 667 | } | ||
| 668 | async_buffers.emplace_back(download_map); | ||
| 669 | } | ||
| 670 | committed_downloads.emplace_back(std::move(uncommitted_downloads)); | ||
| 650 | uncommitted_downloads.clear(); | 671 | uncommitted_downloads.clear(); |
| 651 | } | 672 | } |
| 652 | 673 | ||
| @@ -655,37 +676,58 @@ void TextureCache<P>::PopAsyncFlushes() { | |||
| 655 | if (committed_downloads.empty()) { | 676 | if (committed_downloads.empty()) { |
| 656 | return; | 677 | return; |
| 657 | } | 678 | } |
| 658 | const std::span<const ImageId> download_ids = committed_downloads.front(); | 679 | if constexpr (IMPLEMENTS_ASYNC_DOWNLOADS) { |
| 659 | if (download_ids.empty()) { | 680 | const std::span<const ImageId> download_ids = committed_downloads.front(); |
| 660 | committed_downloads.pop(); | 681 | if (download_ids.empty()) { |
| 661 | return; | 682 | committed_downloads.pop_front(); |
| 662 | } | 683 | async_buffers.pop_front(); |
| 663 | size_t total_size_bytes = 0; | 684 | return; |
| 664 | for (const ImageId image_id : download_ids) { | 685 | } |
| 665 | total_size_bytes += slot_images[image_id].unswizzled_size_bytes; | 686 | auto download_map = *async_buffers.front(); |
| 666 | } | 687 | std::span<u8> download_span = download_map.mapped_span; |
| 667 | auto download_map = runtime.DownloadStagingBuffer(total_size_bytes); | 688 | for (size_t i = download_ids.size(); i > 0; i--) { |
| 668 | const size_t original_offset = download_map.offset; | 689 | const ImageBase& image = slot_images[download_ids[i - 1]]; |
| 669 | for (const ImageId image_id : download_ids) { | 690 | const auto copies = FullDownloadCopies(image.info); |
| 670 | Image& image = slot_images[image_id]; | 691 | download_map.offset -= Common::AlignUp(image.unswizzled_size_bytes, 64); |
| 671 | const auto copies = FullDownloadCopies(image.info); | 692 | std::span<u8> download_span_alt = download_span.subspan(download_map.offset); |
| 672 | image.DownloadMemory(download_map, copies); | 693 | SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, download_span_alt, |
| 673 | download_map.offset += image.unswizzled_size_bytes; | 694 | swizzle_data_buffer); |
| 674 | } | 695 | } |
| 675 | // Wait for downloads to finish | 696 | runtime.FreeDeferredStagingBuffer(download_map); |
| 676 | runtime.Finish(); | 697 | committed_downloads.pop_front(); |
| 677 | 698 | async_buffers.pop_front(); | |
| 678 | download_map.offset = original_offset; | 699 | } else { |
| 679 | std::span<u8> download_span = download_map.mapped_span; | 700 | const std::span<const ImageId> download_ids = committed_downloads.front(); |
| 680 | for (const ImageId image_id : download_ids) { | 701 | if (download_ids.empty()) { |
| 681 | const ImageBase& image = slot_images[image_id]; | 702 | committed_downloads.pop_front(); |
| 682 | const auto copies = FullDownloadCopies(image.info); | 703 | return; |
| 683 | SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, download_span, | 704 | } |
| 684 | swizzle_data_buffer); | 705 | size_t total_size_bytes = 0; |
| 685 | download_map.offset += image.unswizzled_size_bytes; | 706 | for (const ImageId image_id : download_ids) { |
| 686 | download_span = download_span.subspan(image.unswizzled_size_bytes); | 707 | total_size_bytes += slot_images[image_id].unswizzled_size_bytes; |
| 708 | } | ||
| 709 | auto download_map = runtime.DownloadStagingBuffer(total_size_bytes); | ||
| 710 | const size_t original_offset = download_map.offset; | ||
| 711 | for (const ImageId image_id : download_ids) { | ||
| 712 | Image& image = slot_images[image_id]; | ||
| 713 | const auto copies = FullDownloadCopies(image.info); | ||
| 714 | image.DownloadMemory(download_map, copies); | ||
| 715 | download_map.offset += image.unswizzled_size_bytes; | ||
| 716 | } | ||
| 717 | // Wait for downloads to finish | ||
| 718 | runtime.Finish(); | ||
| 719 | download_map.offset = original_offset; | ||
| 720 | std::span<u8> download_span = download_map.mapped_span; | ||
| 721 | for (const ImageId image_id : download_ids) { | ||
| 722 | const ImageBase& image = slot_images[image_id]; | ||
| 723 | const auto copies = FullDownloadCopies(image.info); | ||
| 724 | SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, download_span, | ||
| 725 | swizzle_data_buffer); | ||
| 726 | download_map.offset += image.unswizzled_size_bytes; | ||
| 727 | download_span = download_span.subspan(image.unswizzled_size_bytes); | ||
| 728 | } | ||
| 729 | committed_downloads.pop_front(); | ||
| 687 | } | 730 | } |
| 688 | committed_downloads.pop(); | ||
| 689 | } | 731 | } |
| 690 | 732 | ||
| 691 | template <class P> | 733 | template <class P> |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 6b2898705..4eea1f609 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -92,6 +92,8 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI | |||
| 92 | static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; | 92 | static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; |
| 93 | /// True when the API can provide info about the memory of the device. | 93 | /// True when the API can provide info about the memory of the device. |
| 94 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; | 94 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; |
| 95 | /// True when the API can do asynchronous texture downloads. | ||
| 96 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = P::IMPLEMENTS_ASYNC_DOWNLOADS; | ||
| 95 | 97 | ||
| 96 | static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()}; | 98 | static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()}; |
| 97 | 99 | ||
| @@ -106,6 +108,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI | |||
| 106 | using ImageView = typename P::ImageView; | 108 | using ImageView = typename P::ImageView; |
| 107 | using Sampler = typename P::Sampler; | 109 | using Sampler = typename P::Sampler; |
| 108 | using Framebuffer = typename P::Framebuffer; | 110 | using Framebuffer = typename P::Framebuffer; |
| 111 | using AsyncBuffer = typename P::AsyncBuffer; | ||
| 109 | 112 | ||
| 110 | struct BlitImages { | 113 | struct BlitImages { |
| 111 | ImageId dst_id; | 114 | ImageId dst_id; |
| @@ -403,7 +406,8 @@ private: | |||
| 403 | 406 | ||
| 404 | // TODO: This data structure is not optimal and it should be reworked | 407 | // TODO: This data structure is not optimal and it should be reworked |
| 405 | std::vector<ImageId> uncommitted_downloads; | 408 | std::vector<ImageId> uncommitted_downloads; |
| 406 | std::queue<std::vector<ImageId>> committed_downloads; | 409 | std::deque<std::vector<ImageId>> committed_downloads; |
| 410 | std::deque<std::optional<AsyncBuffer>> async_buffers; | ||
| 407 | 411 | ||
| 408 | struct LRUItemParams { | 412 | struct LRUItemParams { |
| 409 | using ObjectType = ImageId; | 413 | using ObjectType = ImageId; |