MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextureCollection.cpp
Go to the documentation of this file.
2
4
6
7namespace MayaFlux::Kakshya {
8
10using Portal::Graphics::TextureLoom;
11
12namespace {
13
14 /**
15 * @brief The largest rectangle of the source's aspect ratio that fits
16 * centred in a @p dst_w x @p dst_h image.
17 */
18 vk::Rect2D fitted(uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h)
19 {
20 const double scale = std::min(
21 static_cast<double>(dst_w) / static_cast<double>(src_w),
22 static_cast<double>(dst_h) / static_cast<double>(src_h));
23
24 const auto w = std::clamp(static_cast<uint32_t>(std::lround(src_w * scale)), 1U, dst_w);
25 const auto h = std::clamp(static_cast<uint32_t>(std::lround(src_h * scale)), 1U, dst_h);
26
27 return {
28 vk::Offset2D { static_cast<int32_t>((dst_w - w) / 2), static_cast<int32_t>((dst_h - h) / 2) },
29 vk::Extent2D { w, h }
30 };
31 }
32
33} // namespace
34
36 : TextureContainer(spec.width, spec.height, spec.format, LayerCount {})
37 , m_spec(spec)
38{
39}
40
42{
43 if (m_spec.ring_layers > 0 || m_spec.max_bytes == 0)
44 return false;
45
46 return (static_cast<uint64_t>(get_layer_count()) + 1) * byte_size() > m_spec.max_bytes;
47}
48
49bool TextureCollection::append(const std::shared_ptr<Core::VKImage>& image)
50{
51 if (!image || !image->is_initialized()) {
53 "TextureCollection::append called with an uninitialised image");
54 return false;
55 }
56
57 if (is_full()) {
58 if (!m_full_reported) {
60 "TextureCollection is full at {} layers ({} byte cap)", get_layer_count(), m_spec.max_bytes);
61 m_full_reported = true;
62 }
63 return false;
64 }
65
66 const bool reuse = m_spec.ring_layers > 0 && m_write_head >= m_spec.ring_layers;
67 const auto slot = reuse
68 ? static_cast<uint32_t>(m_write_head % m_spec.ring_layers)
70
71 auto target = reuse
72 ? layer_image(slot)
74
75 if (!target || !copy_into(image, target))
76 return false;
77
78 if (reuse) {
79 hold_layer(slot);
80 } else {
81 append_image_layer(std::move(target));
82 }
83
85 return true;
86}
87
89 const std::shared_ptr<Core::VKImage>& image,
90 const std::shared_ptr<Core::VKImage>& target)
91{
92 auto& loom = TextureLoom::instance();
93
94 if (!m_blank) {
95 const std::vector<uint8_t> zeros(byte_size(), 0);
96 m_blank = loom.create_2d(get_width(), get_height(), get_format(), zeros.data());
97 if (!m_blank)
98 return false;
99 }
100
101 const bool same_extent = image->get_width() == get_width() && image->get_height() == get_height();
102 const auto filter = same_extent || !loom.can_blit(image, target, FilterMode::LINEAR)
103 ? FilterMode::NEAREST
104 : FilterMode::LINEAR;
105
106 if (!loom.can_blit(image, target, filter)) {
108 "TextureCollection::append cannot blit {} into {}",
109 vk::to_string(image->get_format()), vk::to_string(target->get_format()));
110 return false;
111 }
112
113 if (same_extent)
114 return loom.blit_layer(image, target, { .filter = filter });
115
116 return loom.blit_layer(m_blank, target, { .filter = FilterMode::NEAREST })
117 && loom.blit_layer(image, target,
118 { .dst = fitted(image->get_width(), image->get_height(), get_width(), get_height()), .filter = filter });
119}
120
121} // namespace MayaFlux::Kakshya
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
IO::ImageData image
Definition Decoder.cpp:47
bool format
uint32_t h
Definition InkPress.cpp:29
float src_w
float src_h
uint32_t width
uint32_t height
TextureCollection(const TextureCollectionSpec &spec)
bool is_full() const
True when a linear collection cannot take another layer.
bool copy_into(const std::shared_ptr< Core::VKImage > &image, const std::shared_ptr< Core::VKImage > &target)
bool append(const std::shared_ptr< Core::VKImage > &image)
Copy image into the next layer.
std::shared_ptr< Core::VKImage > m_blank
void hold_layer(uint32_t layer)
Mark layer as held on the GPU after its image was rewritten.
uint32_t append_image_layer(std::shared_ptr< Core::VKImage > image)
Append one layer held on the GPU by image.
std::shared_ptr< Core::VKImage > layer_image(uint32_t layer) const
The GPU image backing layer, without uploading CPU pixels.
size_t byte_size() const
Total byte count of the pixel buffer.
SignalSourceContainer wrapping GPU texture data as addressable pixel bytes.
std::shared_ptr< Core::VKImage > create_2d(uint32_t width, uint32_t height, ImageFormat format=ImageFormat::RGBA8, const void *data=nullptr, uint32_t mip_levels=1)
Create a 2D texture.
@ ContainerProcessing
Container operations (Kakshya - file/stream/region processing)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
Tendency< D, float > scale(const Tendency< D, float > &t, float factor)
Uniform scaling of a scalar-output tendency.
Definition Tendency.hpp:98
FilterMode
Texture filtering mode.
Describes a TextureCollection so it can be built by designated initializer.
Exact layer count for subclasses, zero allowed.