Skip to content

Commit 39af23c

Browse files
feat: use gpu texture in screen consumer
* Add texture property to const_frame that references the texture on the gpu * Replace GPU-CPU-GPU copy with GPU texture in screen consumer
1 parent c04143d commit 39af23c

File tree

9 files changed

+84
-120
lines changed

9 files changed

+84
-120
lines changed

src/accelerator/ogl/image/image_mixer.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,29 @@ class image_renderer
8484
{
8585
}
8686

87-
std::future<array<const std::uint8_t>> operator()(std::vector<layer> layers,
88-
const core::video_format_desc& format_desc)
87+
std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<texture>>
88+
operator()(std::vector<layer> layers, const core::video_format_desc& format_desc)
8989
{
9090
if (layers.empty()) { // Bypass GPU with empty frame.
91-
static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_, 0);
92-
return make_ready_future(array<const std::uint8_t>(buffer.data(), format_desc.size, true));
91+
static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_,
92+
0);
93+
return {make_ready_future(array<const std::uint8_t>(buffer.data(), format_desc.size, true)), nullptr};
9394
}
9495

95-
return flatten(ogl_->dispatch_async(
96-
[=, layers = std::move(layers)]() mutable -> std::shared_future<array<const std::uint8_t>> {
97-
auto target_texture = ogl_->create_texture(format_desc.width, format_desc.height, 4, depth_);
96+
std::shared_ptr<texture> target_texture;
97+
std::future<array<const std::uint8_t>> data_future =
98+
ogl_->dispatch_async([=,
99+
&target_texture,
100+
layers = std::move(layers)]() mutable -> std::future<array<const std::uint8_t>> {
101+
target_texture = ogl_->create_texture(format_desc.width, format_desc.height, 4, depth_);
98102

99-
draw(target_texture, std::move(layers), format_desc);
103+
draw(target_texture, std::move(layers), format_desc);
100104

101-
return ogl_->copy_async(target_texture);
102-
}));
105+
return ogl_->copy_async(target_texture);
106+
})
107+
.get();
108+
109+
return {std::move(data_future), target_texture};
103110
}
104111

105112
common::bit_depth depth() const { return depth_; }
@@ -318,7 +325,8 @@ struct image_mixer::impl
318325
layer_stack_.resize(transform_stack_.back().image_transform.layer_depth);
319326
}
320327

321-
std::future<array<const std::uint8_t>> render(const core::video_format_desc& format_desc)
328+
std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<texture>>
329+
render(const core::video_format_desc& format_desc)
322330
{
323331
return renderer_(std::move(layers_), format_desc);
324332
}
@@ -374,7 +382,8 @@ void image_mixer::push(const core::frame_transform& transform) { impl_->push(tra
374382
void image_mixer::visit(const core::const_frame& frame) { impl_->visit(frame); }
375383
void image_mixer::pop() { impl_->pop(); }
376384
void image_mixer::update_aspect_ratio(double aspect_ratio) { impl_->update_aspect_ratio(aspect_ratio); }
377-
std::future<array<const std::uint8_t>> image_mixer::render(const core::video_format_desc& format_desc)
385+
std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<core::texture>>
386+
image_mixer::render(const core::video_format_desc& format_desc)
378387
{
379388
return impl_->render(format_desc);
380389
}

src/accelerator/ogl/image/image_mixer.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ class image_mixer final : public core::image_mixer
4747

4848
image_mixer& operator=(const image_mixer&) = delete;
4949

50-
std::future<array<const std::uint8_t>> render(const core::video_format_desc& format_desc) override;
51-
core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;
50+
std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<core::texture>>
51+
render(const core::video_format_desc& format_desc) override;
52+
core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;
5253
core::mutable_frame
5354
create_frame(const void* video_stream_tag, const core::pixel_format_desc& desc, common::bit_depth depth) override;
5455

src/accelerator/ogl/util/context_egl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ namespace caspar::accelerator::ogl {
1010

1111
struct device_context::impl
1212
{
13+
private:
14+
static EGLContext Prev_Created_Context;
15+
16+
public:
1317
EGLDisplay eglDisplay_;
1418
EGLContext eglContext_;
1519

@@ -46,10 +50,12 @@ struct device_context::impl
4650
CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize OpenGL: eglBindAPI"));
4751
}
4852

49-
eglContext_ = eglCreateContext(eglDisplay_, eglConfig, EGL_NO_CONTEXT, NULL);
53+
eglContext_ = eglCreateContext(eglDisplay_, eglConfig, device_context::impl::Prev_Created_Context, NULL);
5054
if (eglContext_ == EGL_NO_CONTEXT) {
5155
CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize OpenGL: eglCreateContext"));
5256
}
57+
// TODO: Access ought to be protexted bu mutex
58+
device_context::impl::Prev_Created_Context = eglContext_;
5359

5460
if (!eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext_)) {
5561
CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize OpenGL: eglMakeCurrent"));
@@ -68,6 +74,8 @@ struct device_context::impl
6874
}
6975
};
7076

77+
EGLContext device_context::impl::Prev_Created_Context = EGL_NO_CONTEXT;
78+
7179
device_context::device_context()
7280
: impl_(new impl())
7381
{

src/accelerator/ogl/util/texture.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@
2222
#pragma once
2323

2424
#include <common/bit_depth.h>
25+
#include <core/frame/frame.h>
2526
#include <memory>
2627

2728
namespace caspar { namespace accelerator { namespace ogl {
2829

29-
class texture final
30+
class texture final : public core::texture
3031
{
3132
public:
3233
texture(int width, int height, int stride, common::bit_depth depth = common::bit_depth::bit8);
@@ -45,8 +46,9 @@ class texture final
4546

4647
void attach();
4748
void clear();
48-
void bind(int index);
49-
void unbind();
49+
50+
virtual void bind(int index) override;
51+
virtual void unbind() override;
5052

5153
int width() const;
5254
int height() const;

src/core/frame/frame.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,32 +92,35 @@ struct const_frame::impl
9292
{
9393
std::vector<array<const std::uint8_t>> image_data_;
9494
array<const std::int32_t> audio_data_;
95-
core::pixel_format_desc desc_ = core::pixel_format_desc(pixel_format::invalid);
95+
core::pixel_format_desc desc_ = core::pixel_format_desc(pixel_format::invalid);
9696
const void* tag_;
9797
frame_geometry geometry_ = frame_geometry::get_default();
9898
std::any opaque_;
99+
std::shared_ptr<core::texture> texture_;
99100

100101
impl(const void* tag,
101102
std::vector<array<const std::uint8_t>> image_data,
102103
array<const std::int32_t> audio_data,
103-
const core::pixel_format_desc& desc)
104+
const core::pixel_format_desc& desc,
105+
std::shared_ptr<core::texture> texture)
104106
: image_data_(std::move(image_data))
105107
, audio_data_(std::move(audio_data))
106108
, desc_(desc)
107109
, tag_(tag)
110+
, texture_(std::move(texture))
108111
{
109112
if (desc_.planes.size() != image_data_.size()) {
110113
CASPAR_THROW_EXCEPTION(invalid_argument());
111114
}
112115
}
113116

114-
115117
impl(mutable_frame&& other)
116118
: image_data_(std::make_move_iterator(other.impl_->image_data_.begin()),
117119
std::make_move_iterator(other.impl_->image_data_.end()))
118120
, audio_data_(std::move(other.impl_->audio_data_))
119121
, desc_(std::move(other.impl_->desc_))
120122
, tag_(other.stream_tag())
123+
, texture_(nullptr)
121124
, geometry_(std::move(other.impl_->geometry_))
122125
{
123126
if (desc_.planes.size() != image_data_.size() && !other.impl_->commit_) {
@@ -130,6 +133,8 @@ struct const_frame::impl
130133

131134
const array<const std::uint8_t>& image_data(std::size_t index) const { return image_data_.at(index); }
132135

136+
std::shared_ptr<core::texture> texture() { return texture_; }
137+
133138
std::size_t width() const { return desc_.planes.at(0).width; }
134139

135140
std::size_t height() const { return desc_.planes.at(0).height; }
@@ -141,8 +146,9 @@ const_frame::const_frame() {}
141146
const_frame::const_frame(const void* tag,
142147
std::vector<array<const std::uint8_t>> image_data,
143148
array<const std::int32_t> audio_data,
144-
const core::pixel_format_desc& desc)
145-
: impl_(new impl(tag, std::move(image_data), std::move(audio_data), desc))
149+
const core::pixel_format_desc& desc,
150+
std::shared_ptr<core::texture> texture)
151+
: impl_(new impl(tag, std::move(image_data), std::move(audio_data), desc, texture))
146152
{
147153
}
148154
const_frame::const_frame(mutable_frame&& other)
@@ -166,26 +172,28 @@ bool const_frame::operator>(const const_frame& other) const
166172
const pixel_format_desc& const_frame::pixel_format_desc() const { return impl_->desc_; }
167173
const array<const std::uint8_t>& const_frame::image_data(std::size_t index) const { return impl_->image_data(index); }
168174
const array<const std::int32_t>& const_frame::audio_data() const { return impl_->audio_data_; }
175+
std::shared_ptr<core::texture> const_frame::texture() { return impl_->texture(); }
169176
std::size_t const_frame::width() const { return impl_->width(); }
170177
std::size_t const_frame::height() const { return impl_->height(); }
171178
std::size_t const_frame::size() const { return impl_->size(); }
172179
const void* const_frame::stream_tag() const { return impl_->tag_; }
173-
const_frame const_frame::with_tag(const void* new_tag) const {
180+
const_frame const_frame::with_tag(const void* new_tag) const
181+
{
174182
if (!impl_) {
175183
return const_frame();
176184
}
177-
185+
178186
std::vector<array<const std::uint8_t>> image_data_copy = impl_->image_data_;
179187
auto new_frame = const_frame(new_tag, std::move(image_data_copy), impl_->audio_data_, impl_->desc_);
180-
188+
181189
new_frame.impl_->geometry_ = impl_->geometry_;
182190
if (impl_->opaque_.has_value()) {
183191
new_frame.impl_->opaque_ = impl_->opaque_;
184192
}
185-
193+
186194
return new_frame;
187195
}
188-
const frame_geometry& const_frame::geometry() const { return impl_->geometry_; }
189-
const std::any& const_frame::opaque() const { return impl_->opaque_; }
196+
const frame_geometry& const_frame::geometry() const { return impl_->geometry_; }
197+
const std::any& const_frame::opaque() const { return impl_->opaque_; }
190198
const_frame::operator bool() const { return impl_ != nullptr && impl_->desc_.format != core::pixel_format::invalid; }
191199
}} // namespace caspar::core

src/core/frame/frame.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111

1212
namespace caspar { namespace core {
1313

14+
class texture
15+
{
16+
public:
17+
virtual ~texture() {}
18+
virtual void bind(int index) = 0;
19+
virtual void unbind() = 0;
20+
};
21+
1422
class mutable_frame final
1523
{
1624
friend class const_frame;
@@ -62,7 +70,8 @@ class const_frame final
6270
explicit const_frame(const void* tag,
6371
std::vector<array<const std::uint8_t>> image_data,
6472
array<const std::int32_t> audio_data,
65-
const struct pixel_format_desc& desc);
73+
const struct pixel_format_desc& desc,
74+
std::shared_ptr<core::texture> texture = nullptr);
6675
const_frame(const const_frame& other);
6776
const_frame(mutable_frame&& other);
6877

@@ -76,6 +85,8 @@ class const_frame final
7685

7786
const array<const std::int32_t>& audio_data() const;
7887

88+
std::shared_ptr<core::texture> texture();
89+
7990
std::size_t width() const;
8091

8192
std::size_t height() const;

src/core/mixer/image/image_mixer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class image_mixer
4848

4949
virtual void update_aspect_ratio(double aspect_ratio) = 0;
5050

51-
virtual std::future<array<const uint8_t>> render(const struct video_format_desc& format_desc) = 0;
51+
virtual std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<core::texture>>
52+
render(const struct video_format_desc& format_desc) = 0;
5253

5354
class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc) override = 0;
5455
class mutable_frame create_frame(const void* video_stream_tag,

src/core/mixer/mixer.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,20 @@ struct mixer::impl
7171
frame.accept(*image_mixer_);
7272
}
7373

74-
auto image = image_mixer_->render(format_desc);
75-
auto audio = audio_mixer_(format_desc, nb_samples);
74+
auto result = image_mixer_->render(format_desc);
75+
auto image = std::move(std::get<0>(result));
76+
auto texture = std::move(std::get<1>(result));
77+
auto audio = audio_mixer_(format_desc, nb_samples);
7678

7779
state_["audio"] = audio_mixer_.state();
7880

7981
auto depth = image_mixer_->depth();
8082

8183
buffer_.push(std::async(std::launch::deferred,
82-
[image = std::move(image),
83-
audio = std::move(audio),
84-
graph = graph_,
84+
[image = std::move(image),
85+
audio = std::move(audio),
86+
texture = std::move(texture),
87+
graph = graph_,
8588
depth,
8689
format_desc,
8790
tag = this]() mutable {
@@ -90,7 +93,7 @@ struct mixer::impl
9093
pixel_format_desc::plane(format_desc.width, format_desc.height, 4, depth));
9194
std::vector<array<const uint8_t>> image_data;
9295
image_data.emplace_back(std::move(image.get()));
93-
return const_frame(tag, std::move(image_data), std::move(audio), desc);
96+
return const_frame(tag, std::move(image_data), std::move(audio), desc, texture);
9497
}));
9598

9699
if (buffer_.size() <= format_desc.field_count) {

0 commit comments

Comments
 (0)