From 2cc9bff205742f49e640e14c6afa8cb9e85277d5 Mon Sep 17 00:00:00 2001 From: ronag Date: Tue, 16 Aug 2011 10:40:38 +0000 Subject: [PATCH] git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1195 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- core/mixer/gpu/ogl_device.cpp | 91 +++++++++++++++++++++++++------- core/mixer/gpu/ogl_device.h | 22 +++++++- core/mixer/image/image_mixer.cpp | 4 +- 3 files changed, 95 insertions(+), 22 deletions(-) diff --git a/core/mixer/gpu/ogl_device.cpp b/core/mixer/gpu/ogl_device.cpp index 95c5ca3b3..34b5366f6 100644 --- a/core/mixer/gpu/ogl_device.cpp +++ b/core/mixer/gpu/ogl_device.cpp @@ -79,10 +79,11 @@ safe_ptr ogl_device::create_device_buffer(size_t width, size_t he { CASPAR_VERIFY(stride > 0 && stride < 5); CASPAR_VERIFY(width > 0 && height > 0); - auto pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)]; + auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)]; std::shared_ptr buffer; - if(!pool->try_pop(buffer)) + if(!pool->items.try_pop(buffer)) { + ++pool->total_count; executor_.invoke([&] { try @@ -102,16 +103,18 @@ safe_ptr ogl_device::create_device_buffer(size_t width, size_t he catch(...) { CASPAR_LOG(error) << L"ogl: create_device_buffer failed!"; + --pool->total_count; throw; } } - }, high_priority); } - - return safe_ptr(buffer.get(), [=](device_buffer*) - { - pool->push(buffer); + + ++pool->usage_count; + + return safe_ptr(buffer.get(), [=](device_buffer*) mutable + { + pool->items.push(buffer); }); } @@ -119,10 +122,11 @@ safe_ptr ogl_device::create_host_buffer(size_t size, host_buffer::u { CASPAR_VERIFY(usage == host_buffer::write_only || usage == host_buffer::read_only); CASPAR_VERIFY(size > 0); - auto pool = host_pools_[usage][size]; + auto& pool = host_pools_[usage][size]; std::shared_ptr buffer; - if(!pool->try_pop(buffer)) + if(!pool->items.try_pop(buffer)) { + ++pool->total_count; executor_.invoke([&] { try @@ -150,28 +154,69 @@ safe_ptr ogl_device::create_host_buffer(size_t size, host_buffer::u catch(...) { CASPAR_LOG(error) << L"ogl: create_host_buffer failed!"; + --pool->total_count; throw; } } - }, high_priority); } - return safe_ptr(buffer.get(), [=](host_buffer*) + ++pool->usage_count; + + return safe_ptr(buffer.get(), [=](host_buffer*) mutable { - executor_.begin_invoke([=] - { + executor_.begin_invoke([=]() mutable + { if(usage == host_buffer::write_only) buffer->map(); else buffer->unmap(); - - pool->push(buffer); - }, high_priority); + pool->items.push(buffer); + }, high_priority); }); } +template +void flush_pool(buffer_pool& pool) +{ + if(pool.flush_count.fetch_and_increment() < 3) + return; + + if(pool.usage_count.fetch_and_store(0) < pool.items.size()) + { + std::shared_ptr buffer; + if(pool.items.try_pop(buffer)) + --pool.total_count; + } + + pool.flush_count = 0; + pool.usage_count = 0; +} + +void ogl_device::flush() +{ + GL(glFlush()); + + try + { + BOOST_FOREACH(auto& pools, device_pools_) + { + BOOST_FOREACH(auto& pool, pools) + flush_pool(*pool.second); + } + BOOST_FOREACH(auto& pools, host_pools_) + { + BOOST_FOREACH(auto& pool, pools) + flush_pool(*pool.second); + } + } + catch(...) + { + CASPAR_LOG_CURRENT_EXCEPTION(); + } +} + void ogl_device::yield() { executor_.yield(); @@ -188,12 +233,22 @@ boost::unique_future ogl_device::gc() BOOST_FOREACH(auto& pools, device_pools_) { BOOST_FOREACH(auto& pool, pools) - pool.second->clear(); + { + auto size = pool.second->items.size(); + std::shared_ptr buffer; + for(int n = 0; n < size && pool.second->items.try_pop(buffer); ++n) + --pool.second->total_count; + } } BOOST_FOREACH(auto& pools, host_pools_) { BOOST_FOREACH(auto& pool, pools) - pool.second->clear(); + { + auto size = pool.second->items.size(); + std::shared_ptr buffer; + for(int n = 0; n < size && pool.second->items.try_pop(buffer); ++n) + --pool.second->total_count; + } } } catch(...) diff --git a/core/mixer/gpu/ogl_device.h b/core/mixer/gpu/ogl_device.h index efb188a43..6c4425760 100644 --- a/core/mixer/gpu/ogl_device.h +++ b/core/mixer/gpu/ogl_device.h @@ -42,6 +42,22 @@ namespace caspar { namespace core { class shader; +template +struct buffer_pool +{ + tbb::atomic total_count; + tbb::atomic usage_count; + tbb::atomic flush_count; + tbb::concurrent_bounded_queue> items; + + buffer_pool() + { + total_count = 0; + usage_count = 0; + flush_count = 0; + } +}; + class ogl_device : boost::noncopyable { std::unordered_map caps_; @@ -54,8 +70,8 @@ class ogl_device : boost::noncopyable std::unique_ptr context_; - std::array>>>, 4> device_pools_; - std::array>>>, 2> host_pools_; + std::array>>, 4> device_pools_; + std::array>>, 2> host_pools_; unsigned int fbo_; @@ -80,6 +96,8 @@ public: void use(shader& shader); + void flush(); + // thread-afe template auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future // noexcept diff --git a/core/mixer/image/image_mixer.cpp b/core/mixer/image/image_mixer.cpp index 2784cc52c..ac24a170c 100644 --- a/core/mixer/image/image_mixer.cpp +++ b/core/mixer/image/image_mixer.cpp @@ -138,8 +138,8 @@ public: active_buffer_ = draw_buffer; - GL(glFlush()); - + channel_.ogl().flush(); // NOTE: This is important, otherwise fences will deadlock. + return host_buffer; } -- 2.39.2