X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fpbo_pool.cpp;fp=futatabi%2Fpbo_pool.cpp;h=1933b31d6a7c71eea1c4f33b16afcfa61aeb6d81;hb=adc0df09f7a9dc88a3c0dbad47a21a805e728862;hp=0000000000000000000000000000000000000000;hpb=02ea864dc5a6dde7450c497581ff18d784ab832c;p=nageru diff --git a/futatabi/pbo_pool.cpp b/futatabi/pbo_pool.cpp new file mode 100644 index 0000000..1933b31 --- /dev/null +++ b/futatabi/pbo_pool.cpp @@ -0,0 +1,79 @@ +#include "pbo_pool.h" + +#include +#include + +#include + +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 buffer, GLenum permissions, GLenum map_bits) + : pbo_size(pbo_size), buffer(buffer), 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 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(stop - start).count()); + } + pbo.upload_done.reset(); + } + + return pbo; +} + +void PBOPool::release_pbo(PBO pbo) +{ + lock_guard 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; +}