Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgperframeallocator_p.h
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6
7
8#ifndef QSSGPERFRAMEALLOCATOR_H
9#define QSSGPERFRAMEALLOCATOR_H
10
11//
12// W A R N I N G
13// -------------
14//
15// This file is not part of the Qt API. It exists purely as an
16// implementation detail. This header file may change from version to
17// version without notice, or even be removed.
18//
19// We mean it.
20//
21
22#include <QtQuick3DRuntimeRender/private/qtquick3druntimerenderglobal_p.h>
23
24QT_BEGIN_NAMESPACE
25
26class QSSGPerFrameAllocator
27{
28 struct FastAllocator
29 {
30 struct Slab;
31
32 enum : size_t {
33 ChunkSize = 8192*2,
34 Alignment = sizeof(void *),
35 SlabSize = ChunkSize - sizeof(Slab *),
36 MaxAlloc = ChunkSize/2 // don't go all the way up to SlabSize, or we'd almost always get a big hole
37 };
38 struct Slab {
39 Slab() = default;
40 Slab(Slab *previous)
41 {
42 previous->next = this;
43 }
44 Slab *next = nullptr;
45 quint8 data[SlabSize];
46 };
47 Q_STATIC_ASSERT(sizeof(Slab) == ChunkSize);
48 Q_STATIC_ASSERT(alignof(Slab) == Alignment);
49
50 Slab *first = nullptr;
51 Slab *current = nullptr;
52 size_t offset = 0;
53
54 FastAllocator()
55 {
56 first = current = new Slab;
57 }
58
59 ~FastAllocator()
60 {
61 Slab *s = first;
62 while (s) {
63 Slab *n = s->next;
64 delete s;
65 s = n;
66 }
67 }
68 void *allocate(size_t size)
69 {
70 size = (size + Alignment - 1) & ~(Alignment - 1);
71 Q_ASSERT(size <= SlabSize);
72 Q_ASSERT(!(offset % Alignment));
73
74 size_t amountLeftInSlab = SlabSize - offset;
75 if (size > amountLeftInSlab) {
76 if (current->next)
77 current = current->next;
78 else
79 current = new Slab(current);
80 offset = 0;
81 }
82
83 quint8 *data = current->data + offset;
84 offset += size;
85 return data;
86 }
87
88 // only reset, so we can re-use the memory
89 void reset() { current = first; offset = 0; }
90 };
91
92 struct LargeAllocator
93 {
94 struct Slab {
95 Slab *next = nullptr;
96 };
97 Slab *current = nullptr;
98
99 LargeAllocator() {}
100
101 // Automatically deallocates everything that hasn't already been deallocated.
102 ~LargeAllocator() { deallocateAll(); }
103
104 void deallocateAll()
105 {
106 while (current) {
107 Slab *n = current->next;
108 ::free(current);
109 current = n;
110 }
111 current = nullptr;
112 }
113
114 void *allocate(size_t size)
115 {
116 quint8 *mem = reinterpret_cast<quint8 *>(::malloc(sizeof(Slab) + size));
117 Slab *s = reinterpret_cast<Slab *>(mem);
118 s->next = current;
119 current = s;
120 return mem + sizeof(Slab);
121 }
122 };
123
124 FastAllocator m_fastAllocator;
125 LargeAllocator m_largeAllocator;
126
127public:
128 QSSGPerFrameAllocator() {}
129
130 inline void *allocate(size_t size)
131 {
132 if (size < FastAllocator::MaxAlloc)
133 return m_fastAllocator.allocate(size);
134
135 return m_largeAllocator.allocate(size);
136 }
137
138 void reset()
139 {
140 m_fastAllocator.reset();
141 m_largeAllocator.deallocateAll();
142 }
143};
144
145QT_END_NAMESPACE
146
147#endif // QSSGPERFRAMEALLOCATOR_H