summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp122
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h104
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
19namespace Vulkan {
20
21CachedBufferEntry::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
26VKBufferCache::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
43VKBufferCache::~VKBufferCache() = default;
44
45u64 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
84u64 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
94std::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
104void 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
114void VKBufferCache::Send() {
115 stream_buffer->Send(buffer_offset - buffer_offset_base);
116}
117
118void 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
16namespace Memory {
17class Memory;
18}
19
20namespace Tegra {
21class MemoryManager;
22}
23
24namespace Vulkan {
25
26class VKDevice;
27class VKFence;
28class VKMemoryManager;
29class VKStreamBuffer;
30
31class CachedBufferEntry final : public RasterizerCacheObject {
32public:
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
56private:
57 VAddr cpu_addr{};
58 std::size_t size{};
59 u64 offset{};
60 std::size_t alignment{};
61};
62
63class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> {
64public:
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
91protected:
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
95private:
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