File: pbo_pool.cpp

package info (click to toggle)
nageru 2.3.2-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 3,120 kB
  • sloc: cpp: 39,131; perl: 94; sh: 18; makefile: 4
file content (79 lines) | stat: -rw-r--r-- 1,855 bytes parent folder | download
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
#include "pbo_pool.h"

#include <chrono>
#include <mutex>

#include <movit/util.h>

using namespace std;
using namespace std::chrono;

once_flag global_pbo_pool_inited;
PBOPool *global_pbo_pool = nullptr;

void init_pbo_pool()
{
	call_once(global_pbo_pool_inited, []{
		global_pbo_pool = new PBOPool;
	});
}

PBOPool::PBOPool(size_t pbo_size, size_t num_pbos, GLenum permissions, GLenum map_bits)
	: pbo_size(pbo_size), permissions(permissions), map_bits(map_bits)
{
	for (size_t i = 0; i < num_pbos; ++i) {
		freelist.push(create_pbo());
	}
}

PBO PBOPool::alloc_pbo()
{
	PBO pbo;
	bool found_pbo = false;
	{
		lock_guard<mutex> lock(freelist_mutex);
		if (!freelist.empty()) {
			pbo = move(freelist.front());
			freelist.pop();
			found_pbo = true;
		}
	}

	if (!found_pbo) {
		fprintf(stderr, "WARNING: Out of PBOs for texture upload, creating a new one\n");
		pbo = create_pbo();
	}
	if (pbo.upload_done != nullptr) {
		if (glClientWaitSync(pbo.upload_done.get(), 0, 0) == GL_TIMEOUT_EXPIRED) {
			steady_clock::time_point start = steady_clock::now();
			glClientWaitSync(pbo.upload_done.get(), /*flags=*/0, GL_TIMEOUT_IGNORED);
			steady_clock::time_point stop = steady_clock::now();

			fprintf(stderr, "WARNING: PBO was not ready after previous upload, had to wait %.1f ms before reusing\n",
				1e3 * duration<double>(stop - start).count());
		}
		pbo.upload_done.reset();
	}

	return pbo;
}

void PBOPool::release_pbo(PBO pbo)
{
	lock_guard<mutex> lock(freelist_mutex);
	freelist.push(move(pbo));
}

PBO PBOPool::create_pbo()
{
	PBO pbo;
	
	glCreateBuffers(1, &pbo.pbo);
	check_error();
	glNamedBufferStorage(pbo.pbo, pbo_size, nullptr, permissions | GL_MAP_PERSISTENT_BIT);
	check_error();
        pbo.ptr = (uint8_t *)glMapNamedBufferRange(pbo.pbo, 0, pbo_size, permissions | map_bits | GL_MAP_PERSISTENT_BIT);
	check_error();

	return pbo;
}