]> git.sesse.net Git - casparcg/commitdiff
Merged GL INFO command from 2.0.
authorHelge Norberg <helge.norberg@svt.se>
Wed, 18 Nov 2015 13:45:06 +0000 (14:45 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 18 Nov 2015 13:45:06 +0000 (14:45 +0100)
17 files changed:
accelerator/accelerator.cpp
accelerator/accelerator.h
accelerator/ogl/util/buffer.cpp
accelerator/ogl/util/buffer.h
accelerator/ogl/util/device.cpp
accelerator/ogl/util/device.h
accelerator/ogl/util/texture.cpp
accelerator/ogl/util/texture.h
common/memory.h
core/fwd.h
protocol/amcp/AMCPCommand.h
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/amcp_command_repository.cpp
protocol/amcp/amcp_command_repository.h
shell/CMakeLists.txt
shell/generate_docs.cpp
shell/server.cpp

index 6f685589a96c432081a828a6348f0b3e8c3f4491..315ad97a345a4d5c8d36ed4c24859dbdf209761f 100644 (file)
@@ -6,11 +6,12 @@
 #include "cpu/image/image_mixer.h"
 #endif
 #include "ogl/image/image_mixer.h"
-
 #include "ogl/util/device.h"
 
 #include <common/env.h>
 
+#include <core/mixer/image/image_mixer.h>
+
 #include <tbb/mutex.h>
 
 namespace caspar { namespace accelerator {
@@ -71,4 +72,9 @@ std::unique_ptr<core::image_mixer> accelerator::create_image_mixer(int channel_i
        return impl_->create_image_mixer(channel_id);
 }
 
+std::shared_ptr<ogl::device> accelerator::get_ogl_device() const
+{
+       return impl_->ogl_device_;
+}
+
 }}
index 4d53522a100ad2c956acdc1df351ac9399bc1252..ef2932861a131f52a55593c7dedf97432baa0fe8 100644 (file)
@@ -3,7 +3,7 @@
 #include <common/forward.h>
 #include <common/memory.h>
 
-#include <core/mixer/image/image_mixer.h>
+#include <core/fwd.h>
 
 #include <boost/noncopyable.hpp>
 
@@ -16,6 +16,8 @@ public:
        ~accelerator();
 
        std::unique_ptr<core::image_mixer> create_image_mixer(int channel_id);
+
+       std::shared_ptr<ogl::device> get_ogl_device() const;
 private:
        struct impl;
        spl::unique_ptr<impl> impl_;
index a34ca570e2f4cc7191d1b3e0e04a3d1879be7564..22b93c004b894fcd717c1e754d6f701d3056f68e 100644 (file)
 
 #include <GL/glew.h>
 
+#include <boost/property_tree/ptree.hpp>
+
 #include <tbb/atomic.h>
 
 namespace caspar { namespace accelerator { namespace ogl {
 
-static tbb::atomic<int> g_w_total_count;
-static tbb::atomic<int> g_r_total_count;
-                                                                                                                                                                                                                                                                                                                               
+static tbb::atomic<int>                        g_w_total_count;
+static tbb::atomic<std::size_t>        g_w_total_size;
+static tbb::atomic<int>                        g_r_total_count;
+static tbb::atomic<std::size_t>        g_r_total_size;
+
 struct buffer::impl : boost::noncopyable
 {      
        GLuint                                          pbo_;
@@ -68,6 +72,9 @@ public:
 
                if(!pbo_)
                        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));
+
+               (usage == usage::write_only ? g_w_total_count : g_r_total_count)        ++;
+               (usage == usage::write_only ? g_w_total_size : g_r_total_size)          += size_;
                
                if(timer.elapsed() > 0.02)
                        CASPAR_LOG(warning) << L"[buffer] Performance warning. Buffer allocation blocked: " << timer.elapsed();
@@ -78,6 +85,8 @@ public:
        ~impl()
        {
                glDeleteBuffers(1, &pbo_);
+               (usage_ == GL_STREAM_DRAW ? g_w_total_size : g_r_total_size)    -= size_;
+               (usage_ == GL_STREAM_DRAW ? g_w_total_count : g_r_total_count)  --;
        }
 
        void* map()
@@ -140,4 +149,16 @@ void buffer::unbind() const{impl_->unbind();}
 std::size_t buffer::size() const { return impl_->size_; }
 int buffer::id() const {return impl_->pbo_;}
 
+boost::property_tree::wptree buffer::info()
+{
+       boost::property_tree::wptree info;
+
+       info.add(L"total_read_count", g_r_total_count);
+       info.add(L"total_write_count", g_w_total_count);
+       info.add(L"total_read_size", g_r_total_size);
+       info.add(L"total_write_size", g_w_total_size);
+
+       return info;
+}
+
 }}}
index 136db96e490de1f7f38a065684a955c779fb53ce..9dbc7799aed13a556376bbebd6ab62ff88597312 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <common/memory.h>
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 #include <cstdint>
 
 namespace caspar { namespace accelerator { namespace ogl {
@@ -64,6 +66,7 @@ public:
 
        int id() const;
 
+       static boost::property_tree::wptree info();
 private:
        struct impl;
        spl::unique_ptr<impl> impl_;
index b1e52ea942ca669f1f43a62041ee25ba65a20f26..ac2159b78da56b51dc42eeac07b4097a80de86d2 100644 (file)
@@ -46,6 +46,7 @@
 #include <tbb/concurrent_queue.h>
 
 #include <boost/utility/declval.hpp>
+#include <boost/property_tree/ptree.hpp>
 
 #include <array>
 #include <unordered_map>
@@ -112,6 +113,93 @@ struct device::impl : public std::enable_shared_from_this<impl>
                        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()
        {       
@@ -274,6 +362,7 @@ array<std::uint8_t>                                                 device::create_array(int size){return impl_->create_ar
 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);}
+boost::property_tree::wptree                           device::info() const { return impl_->info(); }
 std::wstring                                                           device::version() const{return impl_->version();}
 
 
index f010df743b67e5c246850f03ab5c7ad74b6862d0..0907b01d53a7069d00ac694de399392456e29870 100644 (file)
@@ -26,6 +26,8 @@
 #include <common/memory.h>
 #include <common/executor.h>
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 namespace caspar { namespace accelerator { namespace ogl {
 
 class texture;
@@ -70,7 +72,8 @@ public:
 
        // Properties
        
-       std::wstring version() const;
+       boost::property_tree::wptree    info() const;
+       std::wstring                                    version() const;
 
 private:
        struct impl;
index 79e5cdd6c631b07496498093f665f11b174fc20d..18b899984d78e2c6ce433370a8feae0fdee3a996 100644 (file)
@@ -40,7 +40,8 @@ static GLenum FORMAT[] = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA};
 static GLenum INTERNAL_FORMAT[] = {0, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8};       
 static GLenum TYPE[] = {0, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT_8_8_8_8_REV}; 
 
-static tbb::atomic<int> g_total_count;
+static tbb::atomic<int>                        g_total_count;
+static tbb::atomic<std::size_t>        g_total_size;
 
 struct texture::impl : boost::noncopyable
 {
@@ -72,6 +73,8 @@ public:
                }
 
                GL(glBindTexture(GL_TEXTURE_2D, 0));
+               g_total_count++;
+               g_total_size += static_cast<std::size_t>(width * height * stride * (mipmapped ? 1.33 : 1.0));
                //CASPAR_LOG(trace) << "[texture] [" << ++g_total_count << L"] allocated size:" << width*height*stride; 
        }       
 
@@ -95,6 +98,8 @@ public:
        ~impl()
        {
                glDeleteTextures(1, &id_);
+               g_total_size -= static_cast<std::size_t>(width_ * height_ * stride_ * (mipmapped_ ? 1.33 : 1.0));
+               g_total_count--;
        }
        
        void bind()
@@ -169,4 +174,14 @@ bool texture::mipmapped() const { return impl_->mipmapped_; }
 std::size_t texture::size() const { return static_cast<std::size_t>(impl_->width_*impl_->height_*impl_->stride_); }
 int texture::id() const{ return impl_->id_;}
 
+boost::property_tree::wptree texture::info()
+{
+       boost::property_tree::wptree info;
+
+       info.add(L"total_count", g_total_count);
+       info.add(L"total_size", g_total_size);
+
+       return info;
+}
+
 }}}
index c9575747fb08d0736fa15dfac39ddee2b7c2f75e..aa2b0cda27e248f1a06157c50616291adcef4f2c 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <common/memory.h>
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 #include <cstddef>
 
 namespace caspar { namespace accelerator { namespace ogl {
@@ -66,6 +68,7 @@ public:
 
        int id() const;
 
+       static boost::property_tree::wptree info();
 private:
        struct impl;
        spl::unique_ptr<impl> impl_;
index 5d2293a48e9079745958f18c9d8b19d94d6e8ff2..35127f674a5845afb653a1581f28fe6367d12303 100644 (file)
@@ -721,6 +721,12 @@ shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5,
        return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7), std::forward<P8>(p8)));
 }
 
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
+shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9)
+{
+       return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7), std::forward<P8>(p8), std::forward<P9>(p9)));
+}
+
 template<typename T>
 shared_ptr<T>::shared_ptr() 
     : p_(make_shared<T>())
index 433798a8bcab6f6aa41f58a2e9868268f296abc8..df298f53654161a46dcb3be708d712ed266c7b67 100644 (file)
@@ -22,7 +22,8 @@
 
 #include <common/forward.h>
 
-FORWARD3(caspar, core, ogl, class accelerator);
+FORWARD2(caspar, accelerator, class accelerator);
+FORWARD3(caspar, accelerator, ogl, class device);
 
 FORWARD2(caspar, core, class stage);
 FORWARD2(caspar, core, class mixer);
index 33cc8cf98ff0869a12c788437b8c191c96a86347..0eb9a2855bff2297c9d4629aa4e09e1b6c858744 100644 (file)
@@ -25,6 +25,7 @@
 #include "amcp_shared.h"
 #include <core/consumer/frame_consumer.h>
 #include <core/producer/frame_producer.h>
+#include <accelerator/ogl/util/device.h>
 
 #include <boost/algorithm/string.hpp>
 
@@ -45,6 +46,7 @@ namespace amcp {
                std::shared_ptr<core::thumbnail_generator>                              thumb_gen;
                spl::shared_ptr<const core::frame_producer_registry>    producer_registry;
                spl::shared_ptr<const core::frame_consumer_registry>    consumer_registry;
+               std::shared_ptr<accelerator::ogl::device>                               ogl_device;
                std::promise<bool>&                                                                             shutdown_server_now;
                std::vector<std::wstring>                                                               parameters;
 
@@ -63,6 +65,7 @@ namespace amcp {
                                std::shared_ptr<core::thumbnail_generator> thumb_gen,
                                spl::shared_ptr<const core::frame_producer_registry> producer_registry,
                                spl::shared_ptr<const core::frame_consumer_registry> consumer_registry,
+                               std::shared_ptr<accelerator::ogl::device> ogl_device,
                                std::promise<bool>& shutdown_server_now)
                        : client(std::move(client))
                        , channel(channel)
@@ -76,6 +79,7 @@ namespace amcp {
                        , thumb_gen(std::move(thumb_gen))
                        , producer_registry(std::move(producer_registry))
                        , consumer_registry(std::move(consumer_registry))
+                       , ogl_device(std::move(ogl_device))
                        , shutdown_server_now(shutdown_server_now)
                {
                }
index 571c472b6f39e089400e8e49a8da53652f046ee0..5f527b4c509924696322286f6221e714d91b610b 100644 (file)
@@ -2529,6 +2529,31 @@ std::wstring diag_command(command_context& ctx)
        return L"202 DIAG OK\r\n";
 }
 
+void gl_info_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+       sink.short_description(L"Get information about the allocated and pooled OpenGL resources.");
+       sink.syntax(L"GL INFO");
+       sink.para()->text(L"Retrieves information about the allocated and pooled OpenGL resources.");
+}
+
+std::wstring gl_info_command(command_context& ctx)
+{
+       auto device = ctx.ogl_device;
+
+       if (!device)
+               CASPAR_THROW_EXCEPTION(not_supported() << msg_info("GL command only supported with OpenGL accelerator."));
+
+       std::wstringstream result;
+       result << L"201 GL INFO OK\r\n";
+
+       boost::property_tree::xml_writer_settings<std::wstring> w(' ', 3);
+       auto info = device->info();
+       boost::property_tree::write_xml(result, info, w);
+       result << L"\r\n";
+
+       return result.str();
+}
+
 static const int WIDTH = 80;
 
 struct max_width_sink : public core::help_sink
@@ -2884,6 +2909,7 @@ void register_commands(amcp_command_repository& repo)
        repo.register_command(                  L"Query Commands",              L"INFO THREADS",                                info_threads_describer,                         info_threads_command,                   0);
        repo.register_channel_command(  L"Query Commands",              L"INFO DELAY",                                  info_delay_describer,                           info_delay_command,                             0);
        repo.register_command(                  L"Query Commands",              L"DIAG",                                                diag_describer,                                         diag_command,                                   0);
+       repo.register_command(                  L"Query Commands",              L"GL INFO",                                             gl_info_describer,                                      gl_info_command,                                0);
        repo.register_command(                  L"Query Commands",              L"BYE",                                                 bye_describer,                                          bye_command,                                    0);
        repo.register_command(                  L"Query Commands",              L"KILL",                                                kill_describer,                                         kill_command,                                   0);
        repo.register_command(                  L"Query Commands",              L"RESTART",                                             restart_describer,                                      restart_command,                                0);
index b30a0d84bb6ce8e4f95a1665f33f471cb0c48943..06249814def23a49a9bbaed5bc2229f9c7d68b3f 100644 (file)
@@ -71,6 +71,7 @@ struct amcp_command_repository::impl
        spl::shared_ptr<core::help_repository>                                          help_repo;
        spl::shared_ptr<const core::frame_producer_registry>            producer_registry;
        spl::shared_ptr<const core::frame_consumer_registry>            consumer_registry;
+       std::shared_ptr<accelerator::ogl::device>                                       ogl_device;
        std::promise<bool>&                                                                                     shutdown_server_now;
 
        std::map<std::wstring, std::pair<amcp_command_func, int>>       commands;
@@ -85,6 +86,7 @@ struct amcp_command_repository::impl
                        const spl::shared_ptr<core::help_repository>& help_repo,
                        const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,
                        const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,
+                       const std::shared_ptr<accelerator::ogl::device>& ogl_device,
                        std::promise<bool>& shutdown_server_now)
                : thumb_gen(thumb_gen)
                , media_info_repo(media_info_repo)
@@ -93,6 +95,7 @@ struct amcp_command_repository::impl
                , help_repo(help_repo)
                , producer_registry(producer_registry)
                , consumer_registry(consumer_registry)
+               , ogl_device(ogl_device)
                , shutdown_server_now(shutdown_server_now)
        {
                int index = 0;
@@ -114,6 +117,7 @@ amcp_command_repository::amcp_command_repository(
                const spl::shared_ptr<core::help_repository>& help_repo,
                const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,
                const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,
+               const std::shared_ptr<accelerator::ogl::device>& ogl_device,
                std::promise<bool>& shutdown_server_now)
                : impl_(new impl(
                                channels,
@@ -124,6 +128,7 @@ amcp_command_repository::amcp_command_repository(
                                help_repo,
                                producer_registry,
                                consumer_registry,
+                               ogl_device,
                                shutdown_server_now))
 {
 }
@@ -145,6 +150,7 @@ AMCPCommand::ptr_type amcp_command_repository::create_command(const std::wstring
                        self.thumb_gen,
                        self.producer_registry,
                        self.consumer_registry,
+                       self.ogl_device,
                        self.shutdown_server_now);
 
        auto command = find_command(self.commands, s, ctx, tokens);
@@ -184,6 +190,7 @@ AMCPCommand::ptr_type amcp_command_repository::create_channel_command(
                        self.thumb_gen,
                        self.producer_registry,
                        self.consumer_registry,
+                       self.ogl_device,
                        self.shutdown_server_now);
 
        auto command = find_command(self.channel_commands, s, ctx, tokens);
index c92d6ef29e6ac69d19884053cd959bac30109b8c..778c99845dcf1e20d420255d94f316d30fc3a364 100644 (file)
@@ -45,6 +45,7 @@ public:
                        const spl::shared_ptr<core::help_repository>& help_repo,
                        const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,
                        const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,
+                       const std::shared_ptr<accelerator::ogl::device>& ogl_device,
                        std::promise<bool>& shutdown_server_now);
 
        AMCPCommand::ptr_type create_command(const std::wstring& s, IO::ClientInfoPtr client, std::list<std::wstring>& tokens) const;
index e6db0b1fc26890d6a4edc33f6f804005399adb1f..6a514b931ca4d13975e87db9094e78c15d20786f 100644 (file)
@@ -39,6 +39,7 @@ add_precompiled_header(casparcg stdafx.h FORCEINCLUDE)
 add_executable(generate_docs generate_docs.cpp included_modules.h)
 target_link_libraries(generate_docs
                protocol
+               accelerator
 
                "${CASPARCG_MODULE_PROJECTS}"
 
index ea033dfd69d8b47cbd7e51b0e3c3c2f6bb6ed391..f57e541cfff094d806be23db6a39239479b814a7 100644 (file)
@@ -217,6 +217,7 @@ int main(int argc, char** argv)
                        help_repo,
                        producer_registry,
                        consumer_registry,
+                       nullptr,
                        shutdown_server_now);
 
        protocol::amcp::register_commands(repo);
index 4cb769d71ae8c0a46a5bc85925aaf2a1ad2902c8..0523618e4410c8522b96a2ac22a84d5e3083574a 100644 (file)
@@ -43,6 +43,7 @@
 #include <core/producer/text/text_producer.h>
 #include <core/consumer/output.h>
 #include <core/mixer/mixer.h>
+#include <core/mixer/image/image_mixer.h>
 #include <core/thumbnail_generator.h>
 #include <core/producer/media_info/media_info.h>
 #include <core/producer/media_info/media_info_repository.h>
@@ -367,6 +368,7 @@ struct server::impl : boost::noncopyable
                                help_repo_,
                                producer_registry_,
                                consumer_registry_,
+                               accelerator_.get_ogl_device(),
                                shutdown_server_now_);
                amcp::register_commands(*amcp_command_repo_);