6 #include <movit/util.h>
9 using namespace std::chrono;
11 once_flag global_pbo_pool_inited;
12 PBOPool *global_pbo_pool = nullptr;
16 call_once(global_pbo_pool_inited, []{
17 global_pbo_pool = new PBOPool;
21 PBOPool::PBOPool(size_t pbo_size, size_t num_pbos, GLenum buffer, GLenum permissions, GLenum map_bits)
22 : pbo_size(pbo_size), buffer(buffer), permissions(permissions), map_bits(map_bits)
24 for (size_t i = 0; i < num_pbos; ++i) {
25 freelist.push(create_pbo());
29 PBO PBOPool::alloc_pbo()
32 bool found_pbo = false;
34 lock_guard<mutex> lock(freelist_mutex);
35 if (!freelist.empty()) {
36 pbo = move(freelist.front());
43 fprintf(stderr, "WARNING: Out of PBOs for texture upload, creating a new one\n");
46 if (pbo.upload_done != nullptr) {
47 if (glClientWaitSync(pbo.upload_done.get(), 0, 0) == GL_TIMEOUT_EXPIRED) {
48 steady_clock::time_point start = steady_clock::now();
49 glClientWaitSync(pbo.upload_done.get(), /*flags=*/0, GL_TIMEOUT_IGNORED);
50 steady_clock::time_point stop = steady_clock::now();
52 fprintf(stderr, "WARNING: PBO was not ready after previous upload, had to wait %.1f ms before reusing\n",
53 1e3 * duration<double>(stop - start).count());
55 pbo.upload_done.reset();
61 void PBOPool::release_pbo(PBO pbo)
63 lock_guard<mutex> lock(freelist_mutex);
64 freelist.push(move(pbo));
67 PBO PBOPool::create_pbo()
71 glCreateBuffers(1, &pbo.pbo);
73 glNamedBufferStorage(pbo.pbo, pbo_size, nullptr, permissions | GL_MAP_PERSISTENT_BIT);
75 pbo.ptr = (uint8_t *)glMapNamedBufferRange(pbo.pbo, 0, pbo_size, permissions | map_bits | GL_MAP_PERSISTENT_BIT);