summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp41
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h3
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp43
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h7
-rw-r--r--src/video_core/texture_cache/texture_cache.h12
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h6
8 files changed, 75 insertions, 41 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 90e35e307..2de533584 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1299,7 +1299,7 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
1299 if constexpr (IS_IMAGE_UPLOAD) { 1299 if constexpr (IS_IMAGE_UPLOAD) {
1300 image->UploadMemory(buffer->Handle(), offset, copy_span); 1300 image->UploadMemory(buffer->Handle(), offset, copy_span);
1301 } else { 1301 } else {
1302 image->DownloadMemory(buffer->Handle(), offset, copy_span); 1302 texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span);
1303 } 1303 }
1304 return true; 1304 return true;
1305} 1305}
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 0b9c4a904..670d8cafd 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -801,32 +801,34 @@ void Image::UploadMemory(const ImageBufferMap& map,
801 UploadMemory(map.buffer, map.offset, copies); 801 UploadMemory(map.buffer, map.offset, copies);
802} 802}
803 803
804void Image::DownloadMemory(GLuint buffer_handle, size_t buffer_offset, 804void Image::DownloadMemory(std::span<GLuint> buffer_handles, size_t buffer_offset,
805 std::span<const VideoCommon::BufferImageCopy> copies) { 805 std::span<const VideoCommon::BufferImageCopy> copies) {
806 const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); 806 const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
807 if (is_rescaled) { 807 if (is_rescaled) {
808 ScaleDown(); 808 ScaleDown();
809 } 809 }
810 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API 810 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API
811 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_handle); 811 for (auto buffer_handle : buffer_handles) {
812 glPixelStorei(GL_PACK_ALIGNMENT, 1); 812 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_handle);
813 glPixelStorei(GL_PACK_ALIGNMENT, 1);
813 814
814 u32 current_row_length = std::numeric_limits<u32>::max(); 815 u32 current_row_length = std::numeric_limits<u32>::max();
815 u32 current_image_height = std::numeric_limits<u32>::max(); 816 u32 current_image_height = std::numeric_limits<u32>::max();
816 817
817 for (const VideoCommon::BufferImageCopy& copy : copies) { 818 for (const VideoCommon::BufferImageCopy& copy : copies) {
818 if (copy.image_subresource.base_level >= gl_num_levels) { 819 if (copy.image_subresource.base_level >= gl_num_levels) {
819 continue; 820 continue;
820 } 821 }
821 if (current_row_length != copy.buffer_row_length) { 822 if (current_row_length != copy.buffer_row_length) {
822 current_row_length = copy.buffer_row_length; 823 current_row_length = copy.buffer_row_length;
823 glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length); 824 glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length);
824 } 825 }
825 if (current_image_height != copy.buffer_image_height) { 826 if (current_image_height != copy.buffer_image_height) {
826 current_image_height = copy.buffer_image_height; 827 current_image_height = copy.buffer_image_height;
827 glPixelStorei(GL_PACK_IMAGE_HEIGHT, current_image_height); 828 glPixelStorei(GL_PACK_IMAGE_HEIGHT, current_image_height);
829 }
830 CopyImageToBuffer(copy, buffer_offset);
828 } 831 }
829 CopyImageToBuffer(copy, buffer_offset);
830 } 832 }
831 if (is_rescaled) { 833 if (is_rescaled) {
832 ScaleUp(true); 834 ScaleUp(true);
@@ -835,7 +837,10 @@ void Image::DownloadMemory(GLuint buffer_handle, size_t buffer_offset,
835 837
836void Image::DownloadMemory(ImageBufferMap& map, 838void Image::DownloadMemory(ImageBufferMap& map,
837 std::span<const VideoCommon::BufferImageCopy> copies) { 839 std::span<const VideoCommon::BufferImageCopy> copies) {
838 DownloadMemory(map.buffer, map.offset, copies); 840 std::array buffers{
841 map.buffer,
842 };
843 DownloadMemory(buffers, map.offset, copies);
839} 844}
840 845
841GLuint Image::StorageHandle() noexcept { 846GLuint Image::StorageHandle() noexcept {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 911e4607a..67d6910b4 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -212,7 +212,7 @@ public:
212 void UploadMemory(const ImageBufferMap& map, 212 void UploadMemory(const ImageBufferMap& map,
213 std::span<const VideoCommon::BufferImageCopy> copies); 213 std::span<const VideoCommon::BufferImageCopy> copies);
214 214
215 void DownloadMemory(GLuint buffer_handle, size_t buffer_offset, 215 void DownloadMemory(std::span<GLuint> buffer_handle, size_t buffer_offset,
216 std::span<const VideoCommon::BufferImageCopy> copies); 216 std::span<const VideoCommon::BufferImageCopy> copies);
217 217
218 void DownloadMemory(ImageBufferMap& map, std::span<const VideoCommon::BufferImageCopy> copies); 218 void DownloadMemory(ImageBufferMap& map, std::span<const VideoCommon::BufferImageCopy> copies);
@@ -376,6 +376,7 @@ struct TextureCacheParams {
376 using Sampler = OpenGL::Sampler; 376 using Sampler = OpenGL::Sampler;
377 using Framebuffer = OpenGL::Framebuffer; 377 using Framebuffer = OpenGL::Framebuffer;
378 using AsyncBuffer = u32; 378 using AsyncBuffer = u32;
379 using BufferType = GLuint;
379}; 380};
380 381
381using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; 382using TextureCache = VideoCommon::TextureCache<TextureCacheParams>;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 673ab478e..8fc783cc0 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -793,7 +793,7 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
793 if constexpr (IS_IMAGE_UPLOAD) { 793 if constexpr (IS_IMAGE_UPLOAD) {
794 image->UploadMemory(buffer->Handle(), offset, copy_span); 794 image->UploadMemory(buffer->Handle(), offset, copy_span);
795 } else { 795 } else {
796 image->DownloadMemory(buffer->Handle(), offset, copy_span); 796 texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span);
797 } 797 }
798 return true; 798 return true;
799} 799}
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index ae15f6976..e4d077e63 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1,10 +1,11 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include <algorithm> 4#include <algorithm>
5#include <array> 5#include <array>
6#include <span> 6#include <span>
7#include <vector> 7#include <vector>
8#include <boost/container/small_vector.hpp>
8 9
9#include "common/bit_cast.h" 10#include "common/bit_cast.h"
10#include "common/bit_util.h" 11#include "common/bit_util.h"
@@ -1341,16 +1342,20 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
1341 UploadMemory(map.buffer, map.offset, copies); 1342 UploadMemory(map.buffer, map.offset, copies);
1342} 1343}
1343 1344
1344void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset, 1345void Image::DownloadMemory(std::span<VkBuffer> buffers_span, VkDeviceSize offset,
1345 std::span<const VideoCommon::BufferImageCopy> copies) { 1346 std::span<const VideoCommon::BufferImageCopy> copies) {
1346 const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); 1347 const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
1347 if (is_rescaled) { 1348 if (is_rescaled) {
1348 ScaleDown(); 1349 ScaleDown();
1349 } 1350 }
1351 boost::container::small_vector<VkBuffer, 1> buffers_vector{};
1352 for (auto& buffer : buffers_span) {
1353 buffers_vector.push_back(buffer);
1354 }
1350 std::vector vk_copies = TransformBufferImageCopies(copies, offset, aspect_mask); 1355 std::vector vk_copies = TransformBufferImageCopies(copies, offset, aspect_mask);
1351 scheduler->RequestOutsideRenderPassOperationContext(); 1356 scheduler->RequestOutsideRenderPassOperationContext();
1352 scheduler->Record([buffer, image = *original_image, aspect_mask = aspect_mask, 1357 scheduler->Record([buffers = std::move(buffers_vector), image = *original_image,
1353 vk_copies](vk::CommandBuffer cmdbuf) { 1358 aspect_mask = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
1354 const VkImageMemoryBarrier read_barrier{ 1359 const VkImageMemoryBarrier read_barrier{
1355 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 1360 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1356 .pNext = nullptr, 1361 .pNext = nullptr,
@@ -1369,6 +1374,20 @@ void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset,
1369 .layerCount = VK_REMAINING_ARRAY_LAYERS, 1374 .layerCount = VK_REMAINING_ARRAY_LAYERS,
1370 }, 1375 },
1371 }; 1376 };
1377 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1378 0, read_barrier);
1379
1380 for (auto buffer : buffers) {
1381 cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer,
1382 vk_copies);
1383 }
1384
1385 const VkMemoryBarrier memory_write_barrier{
1386 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
1387 .pNext = nullptr,
1388 .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
1389 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
1390 };
1372 const VkImageMemoryBarrier image_write_barrier{ 1391 const VkImageMemoryBarrier image_write_barrier{
1373 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 1392 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1374 .pNext = nullptr, 1393 .pNext = nullptr,
@@ -1387,15 +1406,6 @@ void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset,
1387 .layerCount = VK_REMAINING_ARRAY_LAYERS, 1406 .layerCount = VK_REMAINING_ARRAY_LAYERS,
1388 }, 1407 },
1389 }; 1408 };
1390 const VkMemoryBarrier memory_write_barrier{
1391 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
1392 .pNext = nullptr,
1393 .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
1394 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
1395 };
1396 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1397 0, read_barrier);
1398 cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, vk_copies);
1399 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 1409 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1400 0, memory_write_barrier, nullptr, image_write_barrier); 1410 0, memory_write_barrier, nullptr, image_write_barrier);
1401 }); 1411 });
@@ -1405,7 +1415,10 @@ void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset,
1405} 1415}
1406 1416
1407void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { 1417void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
1408 DownloadMemory(map.buffer, map.offset, copies); 1418 std::array buffers{
1419 map.buffer,
1420 };
1421 DownloadMemory(buffers, map.offset, copies);
1409} 1422}
1410 1423
1411bool Image::IsRescaled() const noexcept { 1424bool Image::IsRescaled() const noexcept {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index d5ee23f8d..422476188 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -1,5 +1,5 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
5 5
@@ -138,7 +138,7 @@ public:
138 void UploadMemory(const StagingBufferRef& map, 138 void UploadMemory(const StagingBufferRef& map,
139 std::span<const VideoCommon::BufferImageCopy> copies); 139 std::span<const VideoCommon::BufferImageCopy> copies);
140 140
141 void DownloadMemory(VkBuffer buffer, VkDeviceSize offset, 141 void DownloadMemory(std::span<VkBuffer> buffers, VkDeviceSize offset,
142 std::span<const VideoCommon::BufferImageCopy> copies); 142 std::span<const VideoCommon::BufferImageCopy> copies);
143 143
144 void DownloadMemory(const StagingBufferRef& map, 144 void DownloadMemory(const StagingBufferRef& map,
@@ -371,6 +371,7 @@ struct TextureCacheParams {
371 using Sampler = Vulkan::Sampler; 371 using Sampler = Vulkan::Sampler;
372 using Framebuffer = Vulkan::Framebuffer; 372 using Framebuffer = Vulkan::Framebuffer;
373 using AsyncBuffer = Vulkan::StagingBufferRef; 373 using AsyncBuffer = Vulkan::StagingBufferRef;
374 using BufferType = VkBuffer;
374}; 375};
375 376
376using TextureCache = VideoCommon::TextureCache<TextureCacheParams>; 377using 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 ed5c768d8..2cd5aa31e 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
@@ -834,6 +834,16 @@ std::pair<typename TextureCache<P>::Image*, BufferImageCopy> TextureCache<P>::Dm
834} 834}
835 835
836template <class P> 836template <class P>
837void TextureCache<P>::DownloadImageIntoBuffer(
838 typename TextureCache<P>::Image* image, typename TextureCache<P>::BufferType buffer,
839 size_t buffer_offset, std::span<const VideoCommon::BufferImageCopy> copies) {
840 std::array buffers{
841 buffer,
842 };
843 image->DownloadMemory(buffers, buffer_offset, copies);
844}
845
846template <class P>
837void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) { 847void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
838 if (False(image.flags & ImageFlagBits::CpuModified)) { 848 if (False(image.flags & ImageFlagBits::CpuModified)) {
839 // Only upload modified images 849 // Only upload modified images
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 5a5b4179c..51f44aed5 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
@@ -119,6 +119,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
119 using Sampler = typename P::Sampler; 119 using Sampler = typename P::Sampler;
120 using Framebuffer = typename P::Framebuffer; 120 using Framebuffer = typename P::Framebuffer;
121 using AsyncBuffer = typename P::AsyncBuffer; 121 using AsyncBuffer = typename P::AsyncBuffer;
122 using BufferType = typename P::BufferType;
122 123
123 struct BlitImages { 124 struct BlitImages {
124 ImageId dst_id; 125 ImageId dst_id;
@@ -215,6 +216,9 @@ public:
215 const Tegra::DMA::ImageCopy& copy_info, const Tegra::DMA::BufferOperand& buffer_operand, 216 const Tegra::DMA::ImageCopy& copy_info, const Tegra::DMA::BufferOperand& buffer_operand,
216 const Tegra::DMA::ImageOperand& image_operand, ImageId image_id, bool modifies_image); 217 const Tegra::DMA::ImageOperand& image_operand, ImageId image_id, bool modifies_image);
217 218
219 void DownloadImageIntoBuffer(Image* image, BufferType buffer, size_t buffer_offset,
220 std::span<const VideoCommon::BufferImageCopy> copies);
221
218 /// Return true when a CPU region is modified from the GPU 222 /// Return true when a CPU region is modified from the GPU
219 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); 223 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size);
220 224