127 {
129 const auto analysis_it =
input.metadata.find(
"vision_analysis");
130 if (analysis_it !=
input.metadata.end() && analysis_it->second.has_value()) {
131 auto analysis = safe_any_cast_or_throw<VisionAnalysis>(analysis_it->second);
132
133 const size_t n = !analysis.frame.boxes.empty()
134 ? analysis.frame.boxes.size()
135 : analysis.frame.contours.size();
136
137 if (n > 1) {
138 uint32_t padded = 1;
139 while (padded < static_cast<uint32_t>(n))
140 padded <<= 1;
141
142 std::vector<float> keys(padded, std::numeric_limits<float>::infinity());
143 for (size_t i = 0; i < n; ++i)
145
146 std::vector<float> indices(padded);
147 for (uint32_t i = 0; i < padded; ++i)
148 indices[i] = static_cast<float>(i);
149
150 const auto k =
static_cast<uint32_t
>(
151 std::ceil(std::log2(static_cast<double>(padded))));
152 const uint32_t total_passes =
k * (
k + 1) / 2;
153 const uint32_t desc = (this->
get_direction() == SortingDirection::DESCENDING) ? 1U : 0
U;
154 const uint32_t
count = padded;
155
156 auto* ctx = dynamic_cast<ShaderExecutionContext<>*>(
158
159 if (ctx) {
160 ctx->in_out(keys).in_out(indices);
161 ctx->set_multipass(total_passes,
162 [
k, desc,
count](uint32_t p,
void* pc_ptr) {
163 uint32_t stage = 0,
pass = 0, remaining = p;
164 for (uint32_t s = 0; s <
k; ++s) {
165 if (remaining <= s) {
166 stage = s;
168 break;
169 }
170 remaining -= (s + 1);
171 }
172 struct PC {
174 };
175 *
static_cast<PC*
>(pc_ptr) = { stage,
pass,
count, desc };
176 });
177
178 auto* ctx = dynamic_cast<ShaderExecutionContext<InputType, OutputType>*>(
181
182 std::vector<float> sorted_idx_floats(padded);
183 ctx->download_binding(1, sorted_idx_floats.data(),
184 padded * sizeof(float));
185
186 auto apply_permutation = [&]<
typename T>(std::vector<T>& coll) {
187 std::vector<T> sorted(n);
188 for (size_t i = 0; i < n; ++i) {
189 const auto src = static_cast<size_t>(sorted_idx_floats[i]);
190 if (src < n)
191 sorted[i] = coll[src];
192 }
193 coll = std::move(sorted);
194 };
195
196 if (!analysis.frame.boxes.empty())
197 apply_permutation(analysis.frame.boxes);
198 if (!analysis.frame.contours.empty())
199 apply_permutation(analysis.frame.contours);
200
202 out.metadata =
input.metadata;
203 out.metadata["vision_analysis"] = std::move(analysis);
204 return out;
205 }
206 }
207 }
208 }
209
211 }
Core::GlobalInputConfig input
std::shared_ptr< GpuExecutionContext< InputType, OutputType > > m_gpu_backend
virtual output_type apply_operation_internal(const input_type &input, const ExecutionContext &context)
Internal execution method - ComputeMatrix can access this.
SortingDirection get_direction() const
Datum< OutputType > output_type
float compute_key(size_t index, const VisionAnalysis &analysis) const
T data
The actual computation data.