#include <tbb/concurrent_queue.h>
#include <boost/utility/declval.hpp>
+#include <boost/property_tree/ptree.hpp>
#include <array>
#include <unordered_map>
~impl()
{
+ auto context = executor_.is_current() ? std::string() : get_context();
+
executor_.invoke([=]
{
+ CASPAR_SCOPED_CONTEXT_MSG(context);
texture_cache_.clear();
for (auto& pool : host_pools_)
device_.reset();
});
}
+
+ boost::property_tree::wptree info() const
+ {
+ boost::property_tree::wptree info;
+
+ boost::property_tree::wptree pooled_device_buffers;
+ size_t total_pooled_device_buffer_size = 0;
+ size_t total_pooled_device_buffer_count = 0;
+
+ for (size_t i = 0; i < device_pools_.size(); ++i)
+ {
+ auto& pools = device_pools_.at(i);
+ bool mipmapping = i > 3;
+ auto stride = mipmapping ? i - 3 : i + 1;
+
+ for (auto& pool : pools)
+ {
+ auto width = pool.first >> 16;
+ auto height = pool.first & 0x0000FFFF;
+ auto size = width * height * stride;
+ auto count = pool.second.size();
+
+ if (count == 0)
+ continue;
+
+ boost::property_tree::wptree pool_info;
+
+ pool_info.add(L"stride", stride);
+ pool_info.add(L"mipmapping", mipmapping);
+ pool_info.add(L"width", width);
+ pool_info.add(L"height", height);
+ pool_info.add(L"size", size);
+ pool_info.add(L"count", count);
+
+ total_pooled_device_buffer_size += size * count;
+ total_pooled_device_buffer_count += count;
+
+ pooled_device_buffers.add_child(L"device_buffer_pool", pool_info);
+ }
+ }
+
+ info.add_child(L"gl.details.pooled_device_buffers", pooled_device_buffers);
+
+ boost::property_tree::wptree pooled_host_buffers;
+ size_t total_read_size = 0;
+ size_t total_write_size = 0;
+ size_t total_read_count = 0;
+ size_t total_write_count = 0;
+
+ for (size_t i = 0; i < host_pools_.size(); ++i)
+ {
+ auto& pools = host_pools_.at(i);
+ auto usage = static_cast<buffer::usage>(i);
+
+ for (auto& pool : pools)
+ {
+ auto size = pool.first;
+ auto count = pool.second.size();
+
+ if (count == 0)
+ continue;
+
+ boost::property_tree::wptree pool_info;
+
+ pool_info.add(L"usage", usage == buffer::usage::read_only ? L"read_only" : L"write_only");
+ pool_info.add(L"size", size);
+ pool_info.add(L"count", count);
+
+ pooled_host_buffers.add_child(L"host_buffer_pool", pool_info);
+
+ (usage == buffer::usage::read_only ? total_read_count : total_write_count) += count;
+ (usage == buffer::usage::read_only ? total_read_size : total_write_size) += size * count;
+ }
+ }
+
+ info.add_child(L"gl.details.pooled_host_buffers", pooled_host_buffers);
+ info.add(L"gl.summary.pooled_device_buffers.total_count", total_pooled_device_buffer_count);
+ info.add(L"gl.summary.pooled_device_buffers.total_size", total_pooled_device_buffer_size);
+ info.add_child(L"gl.summary.all_device_buffers", texture::info());
+ info.add(L"gl.summary.pooled_host_buffers.total_read_count", total_read_count);
+ info.add(L"gl.summary.pooled_host_buffers.total_write_count", total_write_count);
+ info.add(L"gl.summary.pooled_host_buffers.total_read_size", total_read_size);
+ info.add(L"gl.summary.pooled_host_buffers.total_write_size", total_write_size);
+ info.add_child(L"gl.summary.all_host_buffers", buffer::info());
+
+ return info;
+ }
std::wstring version()
{
{
caspar::timer timer;
+ auto context = executor_.is_current() ? std::string() : get_context();
+
buf = executor_.invoke([&]
{
+ CASPAR_SCOPED_CONTEXT_MSG(context);
return std::make_shared<buffer>(size, usage);
}, task_priority::high_priority);
if (strong)
{
- strong->texture_cache_.erase(buf.get());
+ auto context = executor_.is_current() ? std::string() : get_context();
+
+ strong->executor_.invoke([&]
+ {
+ CASPAR_SCOPED_CONTEXT_MSG(context);
+ strong->texture_cache_.erase(buf.get());
+ }, task_priority::high_priority);
+
pool->push(buf);
}
else
std::future<std::shared_ptr<texture>> copy_async(const array<const std::uint8_t>& source, int width, int height, int stride, bool mipmapped)
{
std::shared_ptr<buffer> buf = copy_to_buf(source);
-
+ auto context = executor_.is_current() ? std::string() : get_context();
+
return executor_.begin_invoke([=]() -> std::shared_ptr<texture>
{
+ CASPAR_SCOPED_CONTEXT_MSG(context);
tbb::concurrent_hash_map<buffer*, std::shared_ptr<texture>>::const_accessor a;
if(texture_cache_.find(a, buf.get()))
return spl::make_shared_ptr(a->second);
std::future<std::shared_ptr<texture>> copy_async(const array<std::uint8_t>& source, int width, int height, int stride, bool mipmapped)
{
std::shared_ptr<buffer> buf = copy_to_buf(source);
+ auto context = executor_.is_current() ? std::string() : get_context();
return executor_.begin_invoke([=]() -> std::shared_ptr<texture>
{
+ CASPAR_SCOPED_CONTEXT_MSG(context);
auto texture = create_texture(width, height, stride, mipmapped, false);
texture->copy_from(*buf);
source->copy_to(*buffer);
auto self = shared_from_this();
- auto cmd = [self, buffer]() mutable -> array<const std::uint8_t>
+ auto context = get_context();
+ auto cmd = [self, buffer, context]() mutable -> array<const std::uint8_t>
{
- self->executor_.invoke(std::bind(&buffer::map, std::ref(buffer))); // Defer blocking "map" call until data is needed.
+ self->executor_.invoke([&buffer, &context] // Defer blocking "map" call until data is needed.
+ {
+ CASPAR_LOG_CALL(trace) << "Readback <- " << context;
+ buffer->map();
+ });
return array<const std::uint8_t>(buffer->data(), buffer->size(), true, buffer);
};
return std::async(std::launch::deferred, std::move(cmd));
}
+
+ std::future<void> gc()
+ {
+ return executor_.begin_invoke([=]
+ {
+ CASPAR_LOG(info) << " ogl: Running GC.";
+
+ try
+ {
+ for (auto& pools : device_pools_)
+ {
+ for (auto& pool : pools)
+ pool.second.clear();
+ }
+ for (auto& pools : host_pools_)
+ {
+ for (auto& pool : pools)
+ pool.second.clear();
+ }
+ }
+ catch (...)
+ {
+ CASPAR_LOG_CURRENT_EXCEPTION();
+ }
+ }, task_priority::high_priority);
+ }
};
device::device()
std::future<std::shared_ptr<texture>> device::copy_async(const array<const std::uint8_t>& source, int width, int height, int stride, bool mipmapped){return impl_->copy_async(source, width, height, stride, mipmapped);}
std::future<std::shared_ptr<texture>> device::copy_async(const array<std::uint8_t>& source, int width, int height, int stride, bool mipmapped){ return impl_->copy_async(source, width, height, stride, mipmapped); }
std::future<array<const std::uint8_t>> device::copy_async(const spl::shared_ptr<texture>& source){return impl_->copy_async(source);}
+std::future<void> device::gc() { return impl_->gc(); }
+boost::property_tree::wptree device::info() const { return impl_->info(); }
std::wstring device::version() const{return impl_->version();}