diff options
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 122 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.h | 104 |
2 files changed, 0 insertions, 226 deletions
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 46da81aaa..c36ede898 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -1,125 +1,3 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | 1 | // Copyright 2019 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | #include <memory> | ||
| 7 | #include <optional> | ||
| 8 | #include <tuple> | ||
| 9 | |||
| 10 | #include "common/alignment.h" | ||
| 11 | #include "common/assert.h" | ||
| 12 | #include "core/memory.h" | ||
| 13 | #include "video_core/memory_manager.h" | ||
| 14 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 16 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 17 | #include "video_core/renderer_vulkan/vk_stream_buffer.h" | ||
| 18 | |||
| 19 | namespace Vulkan { | ||
| 20 | |||
| 21 | CachedBufferEntry::CachedBufferEntry(VAddr cpu_addr, std::size_t size, u64 offset, | ||
| 22 | std::size_t alignment, u8* host_ptr) | ||
| 23 | : RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, size{size}, offset{offset}, | ||
| 24 | alignment{alignment} {} | ||
| 25 | |||
| 26 | VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, | ||
| 27 | Memory::Memory& cpu_memory_, | ||
| 28 | VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, | ||
| 29 | VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size) | ||
| 30 | : RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager}, cpu_memory{ | ||
| 31 | cpu_memory_} { | ||
| 32 | const auto usage = vk::BufferUsageFlagBits::eVertexBuffer | | ||
| 33 | vk::BufferUsageFlagBits::eIndexBuffer | | ||
| 34 | vk::BufferUsageFlagBits::eUniformBuffer; | ||
| 35 | const auto access = vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndexRead | | ||
| 36 | vk::AccessFlagBits::eUniformRead; | ||
| 37 | stream_buffer = | ||
| 38 | std::make_unique<VKStreamBuffer>(device, memory_manager, scheduler, size, usage, access, | ||
| 39 | vk::PipelineStageFlagBits::eAllCommands); | ||
| 40 | buffer_handle = stream_buffer->GetBuffer(); | ||
| 41 | } | ||
| 42 | |||
| 43 | VKBufferCache::~VKBufferCache() = default; | ||
| 44 | |||
| 45 | u64 VKBufferCache::UploadMemory(GPUVAddr gpu_addr, std::size_t size, u64 alignment, bool cache) { | ||
| 46 | const auto cpu_addr{tegra_memory_manager.GpuToCpuAddress(gpu_addr)}; | ||
| 47 | ASSERT_MSG(cpu_addr, "Invalid GPU address"); | ||
| 48 | |||
| 49 | // Cache management is a big overhead, so only cache entries with a given size. | ||
| 50 | // TODO: Figure out which size is the best for given games. | ||
| 51 | cache &= size >= 2048; | ||
| 52 | |||
| 53 | u8* const host_ptr{cpu_memory.GetPointer(*cpu_addr)}; | ||
| 54 | if (cache) { | ||
| 55 | const auto entry = TryGet(host_ptr); | ||
| 56 | if (entry) { | ||
| 57 | if (entry->GetSize() >= size && entry->GetAlignment() == alignment) { | ||
| 58 | return entry->GetOffset(); | ||
| 59 | } | ||
| 60 | Unregister(entry); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | AlignBuffer(alignment); | ||
| 65 | const u64 uploaded_offset = buffer_offset; | ||
| 66 | |||
| 67 | if (host_ptr == nullptr) { | ||
| 68 | return uploaded_offset; | ||
| 69 | } | ||
| 70 | |||
| 71 | std::memcpy(buffer_ptr, host_ptr, size); | ||
| 72 | buffer_ptr += size; | ||
| 73 | buffer_offset += size; | ||
| 74 | |||
| 75 | if (cache) { | ||
| 76 | auto entry = std::make_shared<CachedBufferEntry>(*cpu_addr, size, uploaded_offset, | ||
| 77 | alignment, host_ptr); | ||
| 78 | Register(entry); | ||
| 79 | } | ||
| 80 | |||
| 81 | return uploaded_offset; | ||
| 82 | } | ||
| 83 | |||
| 84 | u64 VKBufferCache::UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment) { | ||
| 85 | AlignBuffer(alignment); | ||
| 86 | std::memcpy(buffer_ptr, raw_pointer, size); | ||
| 87 | const u64 uploaded_offset = buffer_offset; | ||
| 88 | |||
| 89 | buffer_ptr += size; | ||
| 90 | buffer_offset += size; | ||
| 91 | return uploaded_offset; | ||
| 92 | } | ||
| 93 | |||
| 94 | std::tuple<u8*, u64> VKBufferCache::ReserveMemory(std::size_t size, u64 alignment) { | ||
| 95 | AlignBuffer(alignment); | ||
| 96 | u8* const uploaded_ptr = buffer_ptr; | ||
| 97 | const u64 uploaded_offset = buffer_offset; | ||
| 98 | |||
| 99 | buffer_ptr += size; | ||
| 100 | buffer_offset += size; | ||
| 101 | return {uploaded_ptr, uploaded_offset}; | ||
| 102 | } | ||
| 103 | |||
| 104 | void VKBufferCache::Reserve(std::size_t max_size) { | ||
| 105 | bool invalidate; | ||
| 106 | std::tie(buffer_ptr, buffer_offset_base, invalidate) = stream_buffer->Reserve(max_size); | ||
| 107 | buffer_offset = buffer_offset_base; | ||
| 108 | |||
| 109 | if (invalidate) { | ||
| 110 | InvalidateAll(); | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | void VKBufferCache::Send() { | ||
| 115 | stream_buffer->Send(buffer_offset - buffer_offset_base); | ||
| 116 | } | ||
| 117 | |||
| 118 | void VKBufferCache::AlignBuffer(std::size_t alignment) { | ||
| 119 | // Align the offset, not the mapped pointer | ||
| 120 | const u64 offset_aligned = Common::AlignUp(buffer_offset, alignment); | ||
| 121 | buffer_ptr += offset_aligned - buffer_offset; | ||
| 122 | buffer_offset = offset_aligned; | ||
| 123 | } | ||
| 124 | |||
| 125 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index daa8ccf66..bc6e584cf 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -3,107 +3,3 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <tuple> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/gpu.h" | ||
| 12 | #include "video_core/rasterizer_cache.h" | ||
| 13 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 15 | |||
| 16 | namespace Memory { | ||
| 17 | class Memory; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Tegra { | ||
| 21 | class MemoryManager; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace Vulkan { | ||
| 25 | |||
| 26 | class VKDevice; | ||
| 27 | class VKFence; | ||
| 28 | class VKMemoryManager; | ||
| 29 | class VKStreamBuffer; | ||
| 30 | |||
| 31 | class CachedBufferEntry final : public RasterizerCacheObject { | ||
| 32 | public: | ||
| 33 | explicit CachedBufferEntry(VAddr cpu_addr, std::size_t size, u64 offset, std::size_t alignment, | ||
| 34 | u8* host_ptr); | ||
| 35 | |||
| 36 | VAddr GetCpuAddr() const override { | ||
| 37 | return cpu_addr; | ||
| 38 | } | ||
| 39 | |||
| 40 | std::size_t GetSizeInBytes() const override { | ||
| 41 | return size; | ||
| 42 | } | ||
| 43 | |||
| 44 | std::size_t GetSize() const { | ||
| 45 | return size; | ||
| 46 | } | ||
| 47 | |||
| 48 | u64 GetOffset() const { | ||
| 49 | return offset; | ||
| 50 | } | ||
| 51 | |||
| 52 | std::size_t GetAlignment() const { | ||
| 53 | return alignment; | ||
| 54 | } | ||
| 55 | |||
| 56 | private: | ||
| 57 | VAddr cpu_addr{}; | ||
| 58 | std::size_t size{}; | ||
| 59 | u64 offset{}; | ||
| 60 | std::size_t alignment{}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { | ||
| 64 | public: | ||
| 65 | explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, Memory::Memory& cpu_memory_, | ||
| 66 | VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, | ||
| 67 | VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size); | ||
| 68 | ~VKBufferCache(); | ||
| 69 | |||
| 70 | /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been | ||
| 71 | /// allocated. | ||
| 72 | u64 UploadMemory(GPUVAddr gpu_addr, std::size_t size, u64 alignment = 4, bool cache = true); | ||
| 73 | |||
| 74 | /// Uploads from a host memory. Returns host's buffer offset where it's been allocated. | ||
| 75 | u64 UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment = 4); | ||
| 76 | |||
| 77 | /// Reserves memory to be used by host's CPU. Returns mapped address and offset. | ||
| 78 | std::tuple<u8*, u64> ReserveMemory(std::size_t size, u64 alignment = 4); | ||
| 79 | |||
| 80 | /// Reserves a region of memory to be used in subsequent upload/reserve operations. | ||
| 81 | void Reserve(std::size_t max_size); | ||
| 82 | |||
| 83 | /// Ensures that the set data is sent to the device. | ||
| 84 | void Send(); | ||
| 85 | |||
| 86 | /// Returns the buffer cache handle. | ||
| 87 | vk::Buffer GetBuffer() const { | ||
| 88 | return buffer_handle; | ||
| 89 | } | ||
| 90 | |||
| 91 | protected: | ||
| 92 | // We do not have to flush this cache as things in it are never modified by us. | ||
| 93 | void FlushObjectInner(const std::shared_ptr<CachedBufferEntry>& object) override {} | ||
| 94 | |||
| 95 | private: | ||
| 96 | void AlignBuffer(std::size_t alignment); | ||
| 97 | |||
| 98 | Tegra::MemoryManager& tegra_memory_manager; | ||
| 99 | Memory::Memory& cpu_memory; | ||
| 100 | |||
| 101 | std::unique_ptr<VKStreamBuffer> stream_buffer; | ||
| 102 | vk::Buffer buffer_handle; | ||
| 103 | |||
| 104 | u8* buffer_ptr = nullptr; | ||
| 105 | u64 buffer_offset = 0; | ||
| 106 | u64 buffer_offset_base = 0; | ||
| 107 | }; | ||
| 108 | |||
| 109 | } // namespace Vulkan | ||