Loading...
Searching...
No Matches
CaptureStrategyCommon.hpp
Go to the documentation of this file.
1#pragma once
2
16#include <QtGui/private/qrhi_p.h>
17
18#include <QDebug>
19
20#include <atomic>
21#include <cstddef>
22#include <cstdint>
23
24namespace score::gfx::interop
25{
26
37{
38 std::atomic<int> pending{-1};
39
40 void publish(std::size_t i) noexcept
41 {
42 pending.store(static_cast<int>(i), std::memory_order_release);
43 }
45 int consume() noexcept { return pending.exchange(-1, std::memory_order_acquire); }
46 void reset() noexcept { pending.store(-1, std::memory_order_relaxed); }
47};
48
73{
74 static constexpr std::size_t kMaxSlots = 32;
75
76 CaptureSlotPublisher publisher;
77
79 std::size_t retireDepth{1};
80
83 int ingest(std::size_t i) noexcept
84 {
85 const int displaced = publisher.pending.exchange(int(i), std::memory_order_acq_rel);
86 if(displaced >= 0 && displaced != int(i))
87 {
88 returns.fetch_or(1u << unsigned(displaced), std::memory_order_release);
89 return displaced;
90 }
91 return -1;
92 }
93
95 int acquire() noexcept
96 {
97 const int slot = publisher.consume();
98 if(slot < 0)
99 return -1;
100
101 ++acquisitions;
102 if(held >= 0 && held != slot && retireN < kMaxSlots)
103 retire[retireN++] = Retired{held, acquisitions};
104 held = slot;
105
106 std::uint32_t freed = 0;
107 std::size_t keep = 0;
108 for(std::size_t i = 0; i < retireN; ++i)
109 {
110 if(acquisitions - retire[i].at >= retireDepth)
111 freed |= 1u << unsigned(retire[i].slot);
112 else
113 retire[keep++] = retire[i];
114 }
115 retireN = keep;
116 if(freed)
117 returns.fetch_or(freed, std::memory_order_release);
118 return slot;
119 }
120
122 std::uint32_t takeReturned() noexcept
123 {
124 return returns.exchange(0, std::memory_order_acquire);
125 }
126
127 void reset() noexcept
128 {
129 publisher.reset();
130 returns.store(0, std::memory_order_relaxed);
131 held = -1;
132 acquisitions = 0;
133 retireN = 0;
134 }
135
136private:
137 struct Retired
138 {
139 int slot{};
140 std::uint64_t at{};
141 };
142 std::atomic<std::uint32_t> returns{0};
143 Retired retire[kMaxSlots]{};
144 std::size_t retireN{0};
145 int held{-1};
146 std::uint64_t acquisitions{0};
147};
148
157 const QRhiTexture* tex, std::uint32_t frameByteSize, const char* tag) noexcept
158{
159 if(!tex)
160 return false;
161 const auto sz = tex->pixelSize();
162 const auto expected = static_cast<std::uint32_t>(sz.width()) * 4u
163 * static_cast<std::uint32_t>(sz.height());
164 if(expected != frameByteSize)
165 {
166 qWarning() << tag << "outputTexture byte size" << expected
167 << "!= captured frame size" << frameByteSize;
168 return false;
169 }
170 return true;
171}
172
173} // namespace score::gfx::interop
bool validateCaptureTextureBytes(const QRhiTexture *tex, std::uint32_t frameByteSize, const char *tag) noexcept
Validate that an RGBA8-typed output texture's byte footprint matches the captured frame size (width *...
Definition CaptureStrategyCommon.hpp:156
Ownership bookkeeping for capture strategies that sample the producer's own buffers instead of copyin...
Definition CaptureStrategyCommon.hpp:73
int ingest(std::size_t i) noexcept
Definition CaptureStrategyCommon.hpp:83
std::uint32_t takeReturned() noexcept
Producer thread. Bitmask of slots the renderer has finished with.
Definition CaptureStrategyCommon.hpp:122
int acquire() noexcept
Render thread. The slot to bind now, or -1 when nothing is pending.
Definition CaptureStrategyCommon.hpp:95
std::size_t retireDepth
framesInFlight + 1, from QRhi::resourceLimit(QRhi::FramesInFlight).
Definition CaptureStrategyCommon.hpp:79
Lock-free single-producer/single-consumer slot handoff.
Definition CaptureStrategyCommon.hpp:37
int consume() noexcept
Returns the published slot index, or -1 if none is pending.
Definition CaptureStrategyCommon.hpp:45