summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h7
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp174
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h11
-rw-r--r--src/video_core/texture_cache/texture_cache.h4
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h2
6 files changed, 193 insertions, 9 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 6956535e5..e70bbec81 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -526,8 +526,8 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image,
526 } 526 }
527} 527}
528 528
529void TextureCacheRuntime::ConvertImage(Image& dst, Image& src, 529void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
530 std::span<const VideoCommon::ImageCopy> copies) { 530 std::span<const VideoCommon::ImageCopy> copies) {
531 LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format); 531 LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format);
532 format_conversion_pass.ConvertImage(dst, src, copies); 532 format_conversion_pass.ConvertImage(dst, src, copies);
533} 533}
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 578f8d523..ad5157d66 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -84,9 +84,13 @@ public:
84 84
85 u64 GetDeviceLocalMemory() const; 85 u64 GetDeviceLocalMemory() const;
86 86
87 bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) {
88 return true;
89 }
90
87 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 91 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
88 92
89 void ConvertImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 93 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
90 94
91 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { 95 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) {
92 UNIMPLEMENTED(); 96 UNIMPLEMENTED();
@@ -338,7 +342,6 @@ struct TextureCacheParams {
338 static constexpr bool FRAMEBUFFER_BLITS = true; 342 static constexpr bool FRAMEBUFFER_BLITS = true;
339 static constexpr bool HAS_EMULATED_COPIES = true; 343 static constexpr bool HAS_EMULATED_COPIES = true;
340 static constexpr bool HAS_DEVICE_MEMORY_INFO = true; 344 static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
341 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = true;
342 345
343 using Runtime = OpenGL::TextureCacheRuntime; 346 using Runtime = OpenGL::TextureCacheRuntime;
344 using Image = OpenGL::Image; 347 using Image = OpenGL::Image;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index af1a11059..02215cfc2 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -308,6 +308,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
308 }; 308 };
309} 309}
310 310
311[[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src,
312 VkImageAspectFlags aspect_mask) noexcept {
313 return VkBufferImageCopy{
314 .bufferOffset = 0,
315 .bufferRowLength = 0,
316 .bufferImageHeight = 0,
317 .imageSubresource = MakeImageSubresourceLayers(
318 is_src ? copy.src_subresource : copy.dst_subresource, aspect_mask),
319 .imageOffset = MakeOffset3D(is_src ? copy.src_offset : copy.dst_offset),
320 .imageExtent = MakeExtent3D(copy.extent),
321 };
322}
323
311[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( 324[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies(
312 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { 325 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) {
313 std::vector<VkBufferCopy> result(copies.size()); 326 std::vector<VkBufferCopy> result(copies.size());
@@ -754,6 +767,167 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
754 return staging_buffer_pool.Request(size, MemoryUsage::Download); 767 return staging_buffer_pool.Request(size, MemoryUsage::Download);
755} 768}
756 769
770bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
771 if (VideoCore::Surface::GetFormatType(dst.info.format) ==
772 VideoCore::Surface::SurfaceType::DepthStencil) {
773 return !device.IsExtShaderStencilExportSupported();
774 }
775 return false;
776}
777
778[[nodiscard]] size_t NextPow2(size_t value) {
779 return static_cast<size_t>(1ULL << ((8U * sizeof(size_t)) - std::countl_zero(value - 1U)));
780}
781
782VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
783 const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL);
784 if (buffer_commits[level]) {
785 return *buffers[level];
786 }
787 const auto new_size = NextPow2(needed_size);
788 VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
789 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
790 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
791 buffers[level] = device.GetLogical().CreateBuffer({
792 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
793 .pNext = nullptr,
794 .flags = 0,
795 .size = new_size,
796 .usage = flags,
797 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
798 .queueFamilyIndexCount = 0,
799 .pQueueFamilyIndices = nullptr,
800 });
801 buffer_commits[level] = std::make_unique<MemoryCommit>(
802 memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal));
803 return *buffers[level];
804}
805
806void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
807 std::span<const VideoCommon::ImageCopy> copies) {
808 std::vector<VkBufferImageCopy> vk_in_copies(copies.size());
809 std::vector<VkBufferImageCopy> vk_out_copies(copies.size());
810 const VkImageAspectFlags src_aspect_mask = src.AspectMask();
811 const VkImageAspectFlags dst_aspect_mask = dst.AspectMask();
812
813 std::ranges::transform(copies, vk_in_copies.begin(), [src_aspect_mask](const auto& copy) {
814 return MakeBufferImageCopy(copy, true, src_aspect_mask);
815 });
816 std::ranges::transform(copies, vk_out_copies.begin(), [dst_aspect_mask](const auto& copy) {
817 return MakeBufferImageCopy(copy, false, dst_aspect_mask);
818 });
819 const u32 img_bpp = BytesPerBlock(src.info.format);
820 size_t total_size = 0;
821 for (const auto& copy : copies) {
822 total_size += copy.extent.width * copy.extent.height * copy.extent.depth * img_bpp;
823 }
824 const VkBuffer copy_buffer = GetTemporaryBuffer(total_size);
825 const VkImage dst_image = dst.Handle();
826 const VkImage src_image = src.Handle();
827 scheduler.RequestOutsideRenderPassOperationContext();
828 scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask,
829 vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) {
830 RangedBarrierRange dst_range;
831 RangedBarrierRange src_range;
832 for (const VkBufferImageCopy& copy : vk_in_copies) {
833 src_range.AddLayers(copy.imageSubresource);
834 }
835 for (const VkBufferImageCopy& copy : vk_out_copies) {
836 dst_range.AddLayers(copy.imageSubresource);
837 }
838 static constexpr VkMemoryBarrier READ_BARRIER{
839 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
840 .pNext = nullptr,
841 .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
842 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
843 };
844 static constexpr VkMemoryBarrier WRITE_BARRIER{
845 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
846 .pNext = nullptr,
847 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
848 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
849 };
850 const std::array pre_barriers{
851 VkImageMemoryBarrier{
852 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
853 .pNext = nullptr,
854 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
855 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
856 VK_ACCESS_TRANSFER_WRITE_BIT,
857 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
858 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
859 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
860 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
861 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
862 .image = src_image,
863 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
864 },
865 };
866 const std::array middle_in_barrier{
867 VkImageMemoryBarrier{
868 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
869 .pNext = nullptr,
870 .srcAccessMask = 0,
871 .dstAccessMask = 0,
872 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
873 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
874 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
875 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
876 .image = src_image,
877 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
878 },
879 };
880 const std::array middle_out_barrier{
881 VkImageMemoryBarrier{
882 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
883 .pNext = nullptr,
884 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
885 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
886 VK_ACCESS_TRANSFER_WRITE_BIT,
887 .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
888 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
889 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
890 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
891 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
892 .image = dst_image,
893 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
894 },
895 };
896 const std::array post_barriers{
897 VkImageMemoryBarrier{
898 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
899 .pNext = nullptr,
900 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
901 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
902 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
903 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
904 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
905 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
906 VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
907 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
908 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
909 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
910 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
911 .image = dst_image,
912 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
913 },
914 };
915 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
916 0, {}, {}, pre_barriers);
917
918 cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
919 vk_in_copies);
920 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
921 0, WRITE_BARRIER, nullptr, middle_in_barrier);
922
923 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
924 0, READ_BARRIER, {}, middle_out_barrier);
925 cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
926 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
927 0, {}, {}, post_barriers);
928 });
929}
930
757void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 931void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
758 const Region2D& dst_region, const Region2D& src_region, 932 const Region2D& dst_region, const Region2D& src_region,
759 Tegra::Engines::Fermi2D::Filter filter, 933 Tegra::Engines::Fermi2D::Filter filter,
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index f5f8f9a74..44e9dcee4 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -61,6 +61,10 @@ public:
61 61
62 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 62 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
63 63
64 bool ShouldReinterpret(Image& dst, Image& src);
65
66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
67
64 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); 68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled);
65 69
66 bool CanAccelerateImageUpload(Image&) const noexcept { 70 bool CanAccelerateImageUpload(Image&) const noexcept {
@@ -82,6 +86,8 @@ public:
82 return true; 86 return true;
83 } 87 }
84 88
89 [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size);
90
85 const Device& device; 91 const Device& device;
86 VKScheduler& scheduler; 92 VKScheduler& scheduler;
87 MemoryAllocator& memory_allocator; 93 MemoryAllocator& memory_allocator;
@@ -90,6 +96,10 @@ public:
90 ASTCDecoderPass& astc_decoder_pass; 96 ASTCDecoderPass& astc_decoder_pass;
91 RenderPassCache& render_pass_cache; 97 RenderPassCache& render_pass_cache;
92 const Settings::ResolutionScalingInfo& resolution; 98 const Settings::ResolutionScalingInfo& resolution;
99
100 constexpr static size_t indexing_slots = 8 * sizeof(size_t);
101 std::array<vk::Buffer, indexing_slots> buffers{};
102 std::array<std::unique_ptr<MemoryCommit>, indexing_slots> buffer_commits{};
93}; 103};
94 104
95class Image : public VideoCommon::ImageBase { 105class Image : public VideoCommon::ImageBase {
@@ -316,7 +326,6 @@ struct TextureCacheParams {
316 static constexpr bool FRAMEBUFFER_BLITS = false; 326 static constexpr bool FRAMEBUFFER_BLITS = false;
317 static constexpr bool HAS_EMULATED_COPIES = false; 327 static constexpr bool HAS_EMULATED_COPIES = false;
318 static constexpr bool HAS_DEVICE_MEMORY_INFO = true; 328 static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
319 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false;
320 329
321 using Runtime = Vulkan::TextureCacheRuntime; 330 using Runtime = Vulkan::TextureCacheRuntime;
322 using Image = Vulkan::Image; 331 using Image = Vulkan::Image;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 4188f93c5..44a0d42ba 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1762,8 +1762,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1762 } 1762 }
1763 UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); 1763 UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D);
1764 UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); 1764 UNIMPLEMENTED_IF(src.info.type != ImageType::e2D);
1765 if constexpr (HAS_PIXEL_FORMAT_CONVERSIONS) { 1765 if (runtime.ShouldReinterpret(dst, src)) {
1766 return runtime.ConvertImage(dst, src, copies); 1766 return runtime.ReinterpretImage(dst, src, copies);
1767 } 1767 }
1768 for (const ImageCopy& copy : copies) { 1768 for (const ImageCopy& copy : copies) {
1769 UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1); 1769 UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1);
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index a9504c0e8..643ad811c 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -59,8 +59,6 @@ class TextureCache {
59 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; 59 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES;
60 /// True when the API can provide info about the memory of the device. 60 /// True when the API can provide info about the memory of the device.
61 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; 61 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
62 /// True when the API provides utilities for pixel format conversions.
63 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = P::HAS_PIXEL_FORMAT_CONVERSIONS;
64 62
65 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; 63 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB;
66 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; 64 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB;