CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GPU/Vulkan/VulkanMemory.h
Views: 1401
1
#pragma once
2
3
#include <cstdint>
4
#include <cstring>
5
#include <functional>
6
#include <vector>
7
8
#include "Common/Data/Collections/FastVec.h"
9
#include "Common/GPU/Vulkan/VulkanContext.h"
10
#include "Common/GPU/GPUBackendCommon.h"
11
12
// Forward declaration
13
VK_DEFINE_HANDLE(VmaAllocation);
14
15
// VulkanMemory
16
//
17
// Vulkan memory management utils.
18
19
// Simple memory pushbuffer pool that can share blocks between the "frames", to reduce the impact of push memory spikes -
20
// a later frame can gobble up redundant buffers from an earlier frame even if they don't share frame index.
21
// NOT thread safe! Can only be used from one thread (our main thread).
22
class VulkanPushPool : public GPUMemoryManager {
23
public:
24
VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage);
25
~VulkanPushPool();
26
27
void Destroy();
28
void BeginFrame();
29
30
const char *Name() const override {
31
return name_;
32
}
33
void GetDebugString(char *buffer, size_t bufSize) const override;
34
35
// When using the returned memory, make sure to bind the returned vkbuf.
36
// It is okay to allocate 0 bytes.
37
uint8_t *Allocate(VkDeviceSize numBytes, VkDeviceSize alignment, VkBuffer *vkbuf, uint32_t *bindOffset) {
38
_dbg_assert_(curBlockIndex_ >= 0);
39
40
Block &block = blocks_[curBlockIndex_];
41
42
VkDeviceSize offset = (block.used + (alignment - 1)) & ~(alignment - 1);
43
if (offset + numBytes <= block.size) {
44
block.used = offset + numBytes;
45
*vkbuf = block.buffer;
46
*bindOffset = (uint32_t)offset;
47
return block.writePtr + offset;
48
}
49
50
NextBlock(numBytes);
51
52
*vkbuf = blocks_[curBlockIndex_].buffer;
53
*bindOffset = 0; // Newly allocated buffer will start at 0.
54
return blocks_[curBlockIndex_].writePtr;
55
}
56
57
// NOTE: If you can avoid this by writing the data directly into memory returned from Allocate,
58
// do so. Savings from avoiding memcpy can be significant.
59
VkDeviceSize Push(const void *data, VkDeviceSize numBytes, int alignment, VkBuffer *vkbuf) {
60
uint32_t bindOffset;
61
uint8_t *ptr = Allocate(numBytes, alignment, vkbuf, &bindOffset);
62
memcpy(ptr, data, numBytes);
63
return bindOffset;
64
}
65
66
size_t GetUsedThisFrame() const;
67
68
private:
69
void NextBlock(VkDeviceSize allocationSize);
70
71
struct Block {
72
~Block();
73
VkBuffer buffer;
74
VmaAllocation allocation;
75
76
VkDeviceSize size;
77
VkDeviceSize used;
78
79
int frameIndex;
80
bool original; // these blocks aren't garbage collected.
81
double lastUsed;
82
83
uint8_t *writePtr;
84
85
void Destroy(VulkanContext *vulkan);
86
};
87
88
Block CreateBlock(size_t sz);
89
90
VulkanContext *vulkan_;
91
VkDeviceSize originalBlockSize_;
92
std::vector<Block> blocks_;
93
VkBufferUsageFlags usage_;
94
int curBlockIndex_ = -1;
95
const char *name_;
96
};
97
98