{\r
CASPAR_VERIFY(stride > 0 && stride < 5);\r
CASPAR_VERIFY(width > 0 && height > 0);\r
- auto pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
+ auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
std::shared_ptr<device_buffer> buffer;\r
- if(!pool->try_pop(buffer)) \r
+ if(!pool->items.try_pop(buffer)) \r
{\r
+ ++pool->total_count;\r
executor_.invoke([&]\r
{ \r
try\r
catch(...)\r
{\r
CASPAR_LOG(error) << L"ogl: create_device_buffer failed!";\r
+ --pool->total_count;\r
throw;\r
}\r
}\r
-\r
}, high_priority); \r
}\r
- \r
- return safe_ptr<device_buffer>(buffer.get(), [=](device_buffer*)\r
- {\r
- pool->push(buffer);\r
+ \r
+ ++pool->usage_count;\r
+\r
+ return safe_ptr<device_buffer>(buffer.get(), [=](device_buffer*) mutable\r
+ { \r
+ pool->items.push(buffer); \r
});\r
}\r
\r
{\r
CASPAR_VERIFY(usage == host_buffer::write_only || usage == host_buffer::read_only);\r
CASPAR_VERIFY(size > 0);\r
- auto pool = host_pools_[usage][size];\r
+ auto& pool = host_pools_[usage][size];\r
std::shared_ptr<host_buffer> buffer;\r
- if(!pool->try_pop(buffer))\r
+ if(!pool->items.try_pop(buffer))\r
{\r
+ ++pool->total_count;\r
executor_.invoke([&]\r
{\r
try\r
catch(...)\r
{\r
CASPAR_LOG(error) << L"ogl: create_host_buffer failed!";\r
+ --pool->total_count;\r
throw; \r
}\r
}\r
-\r
}, high_priority); \r
}\r
\r
- return safe_ptr<host_buffer>(buffer.get(), [=](host_buffer*)\r
+ ++pool->usage_count;\r
+\r
+ return safe_ptr<host_buffer>(buffer.get(), [=](host_buffer*) mutable\r
{\r
- executor_.begin_invoke([=]\r
- {\r
+ executor_.begin_invoke([=]() mutable\r
+ { \r
if(usage == host_buffer::write_only)\r
buffer->map();\r
else\r
buffer->unmap();\r
- \r
- pool->push(buffer);\r
\r
- }, high_priority);\r
+ pool->items.push(buffer);\r
+ }, high_priority); \r
});\r
}\r
\r
+template<typename T>\r
+void flush_pool(buffer_pool<T>& pool)\r
+{ \r
+ if(pool.flush_count.fetch_and_increment() < 3)\r
+ return;\r
+\r
+ if(pool.usage_count.fetch_and_store(0) < pool.items.size())\r
+ {\r
+ std::shared_ptr<T> buffer;\r
+ if(pool.items.try_pop(buffer))\r
+ --pool.total_count;\r
+ }\r
+\r
+ pool.flush_count = 0;\r
+ pool.usage_count = 0;\r
+}\r
+\r
+void ogl_device::flush()\r
+{\r
+ GL(glFlush()); \r
+ \r
+ try\r
+ {\r
+ BOOST_FOREACH(auto& pools, device_pools_)\r
+ {\r
+ BOOST_FOREACH(auto& pool, pools)\r
+ flush_pool(*pool.second);\r
+ }\r
+ BOOST_FOREACH(auto& pools, host_pools_)\r
+ {\r
+ BOOST_FOREACH(auto& pool, pools)\r
+ flush_pool(*pool.second);\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+}\r
+\r
void ogl_device::yield()\r
{\r
executor_.yield();\r
BOOST_FOREACH(auto& pools, device_pools_)\r
{\r
BOOST_FOREACH(auto& pool, pools)\r
- pool.second->clear();\r
+ {\r
+ auto size = pool.second->items.size();\r
+ std::shared_ptr<device_buffer> buffer;\r
+ for(int n = 0; n < size && pool.second->items.try_pop(buffer); ++n)\r
+ --pool.second->total_count;\r
+ }\r
}\r
BOOST_FOREACH(auto& pools, host_pools_)\r
{\r
BOOST_FOREACH(auto& pool, pools)\r
- pool.second->clear();\r
+ {\r
+ auto size = pool.second->items.size();\r
+ std::shared_ptr<host_buffer> buffer;\r
+ for(int n = 0; n < size && pool.second->items.try_pop(buffer); ++n)\r
+ --pool.second->total_count;\r
+ }\r
}\r
}\r
catch(...)\r
\r
class shader;\r
\r
+template<typename T>\r
+struct buffer_pool\r
+{\r
+ tbb::atomic<int> total_count;\r
+ tbb::atomic<int> usage_count;\r
+ tbb::atomic<int> flush_count;\r
+ tbb::concurrent_bounded_queue<std::shared_ptr<T>> items;\r
+\r
+ buffer_pool()\r
+ {\r
+ total_count = 0;\r
+ usage_count = 0;\r
+ flush_count = 0;\r
+ }\r
+};\r
+\r
class ogl_device : boost::noncopyable\r
{ \r
std::unordered_map<GLenum, bool> caps_;\r
\r
std::unique_ptr<sf::Context> context_;\r
\r
- std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<tbb::concurrent_bounded_queue<std::shared_ptr<device_buffer>>>>, 4> device_pools_;\r
- std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<tbb::concurrent_bounded_queue<std::shared_ptr<host_buffer>>>>, 2> host_pools_;\r
+ std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<buffer_pool<device_buffer>>>, 4> device_pools_;\r
+ std::array<tbb::concurrent_unordered_map<size_t, safe_ptr<buffer_pool<host_buffer>>>, 2> host_pools_;\r
\r
unsigned int fbo_;\r
\r
\r
void use(shader& shader);\r
\r
+ void flush();\r
+\r
// thread-afe\r
template<typename Func>\r
auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r