Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include "Headers/glMemoryManager.h"
#include "Platform/Video/OpenGL/Headers/GLWrapper.h"

#include "Core/Headers/Console.h"

namespace Divide {
namespace GLUtil {


static vectorImpl<VBO> g_globalVBOs;

U32 VBO::getChunkCountForSize(size_t sizeInBytes) {
    return to_uint(std::ceil(to_float(sizeInBytes) / MAX_VBO_CHUNK_SIZE_BYTES));
}

VBO::VBO() : _handle(0),
             _usage(GL_NONE),
             _filledManually(false)
{
    _chunkUsageState.fill(std::make_pair(false, 0));
}

VBO::~VBO()
{
}

void VBO::freeAll() {
    if (_handle != 0) {
        GLUtil::freeBuffer(_handle);
        _handle = 0;
    }
    _usage = GL_NONE;
}

U32 VBO::handle() {
    return _handle;
}

bool VBO::checkChunksAvailability(U32 offset, U32 count) {
    assert(MAX_VBO_CHUNK_COUNT > offset);

    std::pair<bool, U32>& chunk = _chunkUsageState[offset];
    U32 freeChunkCount = 0;
    if (!chunk.first) {
        freeChunkCount++;
        for (U32 j = 1; j < MAX_VBO_CHUNK_COUNT - offset; ++j) {
            std::pair<bool, U32>& chunkChild = _chunkUsageState[offset + j];
            if (chunkChild.first) {
                break;
            } else {
                freeChunkCount++;
            }
        }
    }

    return freeChunkCount >= count;
}

bool VBO::allocateChunks(U32 count, GLenum usage, U32& offsetOut) {
    if (_usage == GL_NONE || _usage == usage) {
        for (U32 i = 0; i < MAX_VBO_CHUNK_COUNT; ++i) {
            if (checkChunksAvailability(i, count)) {
                if (_handle == 0) {
                    GLUtil::createAndAllocBuffer(MAX_VBO_SIZE_BYTES, usage, _handle);
                    _usage = usage;
                }
                offsetOut = i;
                _chunkUsageState[i].first = true;
                _chunkUsageState[i].second = count;
                for (U32 j = 1; j < count; ++j) {
                    _chunkUsageState[j + i].first = true;
                }
                return true;
            }
        }
    }

    return false;
}

bool VBO::allocateWhole(U32 count, GLenum usage) {
    assert(_handle == 0);
    GLUtil::createAndAllocBuffer(count * MAX_VBO_CHUNK_SIZE_BYTES, usage, _handle);
    _usage = usage;
    _chunkUsageState.fill(std::make_pair(true, 0));
    _chunkUsageState[0].second = count;
    _filledManually = true;
    return true;
}

void VBO::releaseChunks(U32 offset) {
    if (_filledManually) {
        _chunkUsageState.fill(std::make_pair(false, 0));
        return;
    }

    assert(offset < MAX_VBO_CHUNK_COUNT);
    assert(_chunkUsageState[offset].second != 0);
    U32 childCount = _chunkUsageState[offset].second;
    for (U32 i = 0; i < childCount; ++i) {
        std::pair<bool, U32>& chunkChild = _chunkUsageState[i + offset];
        assert(chunkChild.first);
        chunkChild.first = false;
        chunkChild.second = 0;
    }
}

U32 VBO::getMemUsage() {
    U32 usedBlocks = 0;
    for (std::pair<bool, U32>& chunk : _chunkUsageState) {
        if (chunk.first) {
            usedBlocks++;
        }
    }

    return usedBlocks * MAX_VBO_CHUNK_SIZE_BYTES;
}

bool commitVBO(U32 chunkCount, GLenum usage, GLuint& handleOut, U32& offsetOut) {
    if (chunkCount < VBO::MAX_VBO_CHUNK_COUNT) {
        for (VBO& vbo : g_globalVBOs) {
            if (vbo.allocateChunks(chunkCount, usage, offsetOut)) {
                handleOut = vbo.handle();
                return true;
            }
        }

        VBO vbo;
        if (vbo.allocateChunks(chunkCount, usage, offsetOut)) {
            handleOut = vbo.handle();
            g_globalVBOs.push_back(vbo);
            return true;
        }
    } else {
        VBO vbo;
        if (vbo.allocateWhole(chunkCount, usage)) {
            offsetOut = 0;
            handleOut = vbo.handle();
            g_globalVBOs.push_back(vbo);
            return true;
        }
    }

    return false;
}

bool releaseVBO(GLuint& handle, U32& offset) {
    for (VBO& vbo : g_globalVBOs) {
        if (vbo.handle() == handle) {
            vbo.releaseChunks(offset);
            handle = 0;
            offset = 0;
            return true;
        }
    }

    return false;
}

U32 getVBOMemUsage(GLuint handle) {
    for (VBO& vbo : g_globalVBOs) {
        if (vbo.handle() == handle) {
            return vbo.getMemUsage();
        }
    }

    return 0;
}

U32 getVBOCount() {
    return to_uint(g_globalVBOs.size());
}

void clearVBOs() {
    g_globalVBOs.clear();
}

bufferPtr allocPersistentBuffer(GLuint bufferId,
                                GLsizeiptr bufferSize,
                                BufferStorageMask storageMask,
                                BufferAccessMask accessMask,
                                const bufferPtr data) {
    glNamedBufferStorage(bufferId, bufferSize, data, storageMask);
    bufferPtr ptr = glMapNamedBufferRange(bufferId, 0, bufferSize, accessMask);
    assert(ptr != NULL);
    return ptr;
}

bufferPtr createAndAllocPersistentBuffer(GLsizeiptr bufferSize,
                                         BufferStorageMask storageMask,
                                         BufferAccessMask accessMask,
                                         GLuint& bufferIdOut,
                                         bufferPtr const data) {
    glCreateBuffers(1, &bufferIdOut);
    assert(bufferIdOut != 0 && "GLUtil::allocPersistentBuffer error: buffer creation failed");

    return allocPersistentBuffer(bufferIdOut, bufferSize, storageMask, accessMask,
                                 data);
}

void createAndAllocBuffer(GLsizeiptr bufferSize,
                          GLenum usageMask,
                          GLuint& bufferIdOut,
                          const bufferPtr data) {
    glCreateBuffers(1, &bufferIdOut);
    assert(bufferIdOut != 0 && "GLUtil::allocBuffer error: buffer creation failed");
    glNamedBufferData(bufferIdOut, bufferSize, data, usageMask);
}

void freeBuffer(GLuint& bufferId, bufferPtr mappedPtr) {
    if (bufferId > 0) {
        if (mappedPtr != nullptr) {
            GLboolean result = glUnmapNamedBuffer(bufferId);
            assert(result != GL_FALSE && "GLUtil::freeBuffer error: buffer unmaping failed");
            ACKNOWLEDGE_UNUSED(result);
            mappedPtr = nullptr;
        }
        glDeleteBuffers(1, &bufferId);
        bufferId = 0;
    }
}

};  // namespace GLUtil
};  // namespace Divide

Commits for Divide-Framework/trunk/Source Code/Platform/Video/OpenGL/Buffers/glMemoryManager.cpp

Diff revisions: vs.
Revision Author Commited Message
750 Diff Diff IonutCava picture IonutCava Thu 07 Jul, 2016 16:02:03 +0000

[IonutCava]
- Static analysis based fixes and improvements

743 Diff Diff IonutCava picture IonutCava Tue 28 Jun, 2016 15:55:50 +0000

[IonutCava]
- More performance tuning:
— Move billboarding related camera variable calculation to shaders instead of CPU
— Replace some DIVIDE_ASSERT calls with regular assert calls in really low level code.
— Some cleanup of the GenericDrawCommand class
— glRegularBuffer does an invalidation call before updating
— Misc changes

720 Diff Diff IonutCava picture IonutCava Mon 06 Jun, 2016 15:51:06 +0000

[IonutCava]
- PVS-Studio guided static analysis fixes and optimizations
- Added a flag to SceneState to bypass the Save/Load system not needed for certain types of scenes (menus, cinematics, etc)

619 Diff Diff IonutCava picture IonutCava Fri 08 Jan, 2016 16:23:28 +0000

[IonutCava]
- Memory allocation optimizations
- Large VBO allocation system
- More terrain fixes
- Temporarily disable water and vegetation systems

615 Diff Diff IonutCava picture IonutCava Tue 22 Dec, 2015 16:30:42 +0000

[IonutCava]
not working properly
- Move HiZ buffer to separate render target
- Implement basic, per-scene, auto Save/Load system (works with camera position only for now)
- Fix a few wrong calls in glFramebuffer and glVertexArray
- Re-work skybox rendering

557 Diff Diff IonutCava picture IonutCava Tue 10 Nov, 2015 12:00:20 +0000

[IonutCava]
- Gather all rendering calls from glVertexArray and glGenericVertexData into a single function in glResources: submitRenderCommand.
— This allows both classes to interpret GenericDrawCommands in the same way
- Use unsigned ints for all hasehs instead of size_t to avoid negative number hashes (useful for debugging)

553 Diff Diff IonutCava picture IonutCava Sun 08 Nov, 2015 21:48:10 +0000

[IonutCava]
- Improve VBO allocation system
- Disable mipmap generation for blur FBO in CascadedShadowMaps
- Code cleanup

478 Diff Diff IonutCava picture IonutCava Thu 06 Aug, 2015 15:51:03 +0000

[Ionut]
- Migrated to vc140
- Fixed some code analysis issues
- Added some missing Eclipse files

477 Diff Diff IonutCava picture IonutCava Tue 07 Jul, 2015 16:03:35 +0000

[Ionut]
- Moving to pure OpenGL 4.5 context (Part 2: everything else)

401 IonutCava picture IonutCava Thu 16 Apr, 2015 15:55:47 +0000

[Ionut]
- Hacked together a DSA wrapper that enables the switch between OGL4.4 + GL_EXT_direct_state_access and OGL4.5 + GL_ARB_direct_state_access (some texture issues need debugging)
- Fixed a hardware state check on init
- Multithreaded hw resource loading now uses a conditional variable to check for new load commands instead of checking every 20ms reducing the load on a CPU core significantly