3#include "gaia/ecs/query_adapter_typed.inl"
8 inline TypedQueryExecState build_typed_query_exec_state(
9 [[maybe_unused]] QueryImpl& query, World& world,
const QueryInfo& queryInfo,
const TypedQueryArgMeta* pMetas,
11 TypedQueryExecState state{};
12 QueryImpl::DirectChunkArgEvalDesc directChunkDescs[MAX_ITEMS_IN_QUERY]{};
13 state.argCount = argCount;
15 state.argIds[i] = pMetas[i].termId;
16 state.writeFlags[i] = pMetas[i].isWrite;
17 if (pMetas[i].isWrite) {
18 state.hasWriteArgs =
true;
19 if (state.firstWriteArg == MAX_ITEMS_IN_QUERY)
20 state.firstWriteArg = (uint32_t)i;
22 state.needsInheritedArgIds = state.needsInheritedArgIds || !pMetas[i].isEntity;
23 directChunkDescs[i] = {pMetas[i].termId, pMetas[i].isEntity, pMetas[i].isPair};
26 state.canUseDirectChunkEval =
27 QueryImpl::can_use_direct_chunk_term_eval_descs(world, queryInfo, directChunkDescs, argCount);
28 if (state.needsInheritedArgIds)
29 state.hasInheritedTerms = queryInfo.has_potential_inherited_id_terms();
33#if GAIA_ECS_TEST_HOOKS
34 template <
typename Func>
35 inline QueryImpl::QueryPlan QueryImpl::test_typed_plan(Func func) {
36 auto& queryInfo =
fetch();
39 using InputArgs =
decltype(core::func_args(&Func::operator()));
40 #if GAIA_ASSERT_ENABLED
41 GAIA_ASSERT(typed_query_args_match_query(queryInfo, InputArgs{}));
43 auto& world = *
const_cast<World*
>(queryInfo.world());
44 TypedQueryArgMeta metas[MAX_ITEMS_IN_QUERY]{};
45 const auto argCount = init_typed_query_arg_metas(metas, world, InputArgs{});
46 const auto state = build_typed_query_exec_state(*
this, world, queryInfo, metas, argCount);
51 inline QueryImpl::QueryPlan QueryImpl::test_iter_plan(Constraints constraints) {
52 auto& queryInfo =
fetch();
58 inline void finish_typed_chunk_state(
59 QueryImpl& query, World& world, Chunk* pChunk, uint16_t from, uint16_t to,
const TypedQueryExecState& state);
61 inline void finish_typed_iter_state(QueryImpl& query, Iter& it,
const TypedQueryExecState& state);
63 inline void noop_row_done(uint32_t) {}
65 template <
typename Func,
typename ViewsTuple,
typename... T>
66 inline void invoke_typed_query_row_erased(
67 void* pFunc, Iter& it, ViewsTuple& dataPointerTuple, uint32_t row,
bool directLocalIndex);
69 template <
typename OnRowDone,
typename... T>
70 inline void run_typed_chunk_views(
71 const QueryInfo* pQueryInfo, Iter& it,
void* pFunc,
bool directViews, OnRowDone&& onRowDone,
72 void (*invokeDirectRow)(
73 void*, Iter&, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>&, uint32_t,
bool),
74 void (*invokeMappedRow)(
75 void*, Iter&, std::tuple<
decltype(std::declval<Iter&>().
template view_auto_any<T>())...>&, uint32_t,
77 core::func_type_list<T...>);
79 template <
typename Func,
typename... T>
80 inline void run_typed_chunk_direct_iter_fast_cb(QueryImpl&, Iter& it,
void* pFunc,
const TypedQueryExecState&);
82 template <
typename Func,
typename... T>
84 run_typed_chunk_direct_iter_cb(QueryImpl& query, Iter& it,
void* pFunc,
const TypedQueryExecState& state);
86 template <
typename Func,
typename... T>
87 inline void run_typed_chunk_mapped_iter_cb(
88 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it,
void* pFunc,
const TypedQueryExecState& state);
90 template <
typename Func,
typename... T>
91 GAIA_NODISCARD
inline auto typed_run_direct_fast_chunk_ptr(core::func_type_list<T...>) {
92 return &run_typed_chunk_direct_iter_fast_cb<Func, T...>;
95 template <
typename Func,
typename... T>
96 GAIA_NODISCARD
inline auto typed_run_direct_chunk_ptr(core::func_type_list<T...>) {
97 return &run_typed_chunk_direct_iter_cb<Func, T...>;
100 template <
typename Func,
typename... T>
101 GAIA_NODISCARD
inline auto typed_run_mapped_chunk_ptr(core::func_type_list<T...>) {
102 return &run_typed_chunk_mapped_iter_cb<Func, T...>;
105 template <
typename Func,
typename... T>
106 inline void run_typed_chunk_direct_iter_fast_cb(QueryImpl&, Iter& it,
void* pFunc,
const TypedQueryExecState&) {
107 run_typed_chunk_views(
108 nullptr, it, pFunc,
true, noop_row_done,
109 &invoke_typed_query_row_erased<
110 Func, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>, T...>,
111 &invoke_typed_query_row_erased<
112 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
113 core::func_type_list<T...>{});
116 template <
typename Func,
typename... T>
118 run_typed_chunk_direct_iter_cb(QueryImpl& query, Iter& it,
void* pFunc,
const TypedQueryExecState& state) {
119 auto& func = *
static_cast<Func*
>(pFunc);
120 run_typed_chunk_direct_finish(query, it, func, state, core::func_type_list<T...>{});
123 template <
typename Func,
typename... T>
124 inline void run_typed_chunk_mapped_iter_cb(
125 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it,
void* pFunc,
const TypedQueryExecState& state) {
126 auto& func = *
static_cast<Func*
>(pFunc);
127 run_typed_chunk_mapped_finish(query, queryInfo, it, func, state, core::func_type_list<T...>{});
130 template <
typename Func,
typename... T>
131 inline void each_iter_dispatch(
132 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it, Func& func,
const TypedQueryExecState& state,
133 core::func_type_list<T...>) {
134 if (state.canUseDirectChunkEval) {
135 run_typed_chunk_views(
136 nullptr, it, &func,
true, noop_row_done,
137 &invoke_typed_query_row_erased<
138 Func, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>, T...>,
139 &invoke_typed_query_row_erased<
140 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
141 core::func_type_list<T...>{});
142 finish_typed_chunk_state(
143 query, *it.world(),
const_cast<Chunk*
>(it.chunk()), it.row_begin(), it.row_end(), state);
145 run_typed_chunk_unmapped(query, queryInfo, it, func, state, core::func_type_list<T...>{});
148 template <
typename Func,
typename... T>
149 inline void run_typed_chunk_direct_finish(
150 QueryImpl& query, Iter& it, Func& func,
const TypedQueryExecState& state, core::func_type_list<T...>) {
151 run_typed_chunk_views(
152 nullptr, it, &func,
true, noop_row_done,
153 &invoke_typed_query_row_erased<
154 Func, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>, T...>,
155 &invoke_typed_query_row_erased<
156 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
157 core::func_type_list<T...>{});
158 finish_typed_iter_state(query, it, state);
161 template <
typename Func,
typename... T>
162 inline void run_typed_chunk_mapped_finish(
163 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it, Func& func,
const TypedQueryExecState& state,
164 core::func_type_list<T...>) {
165 run_typed_chunk_views(
166 &queryInfo, it, &func,
false, noop_row_done,
167 &invoke_typed_query_row_erased<
168 Func, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>, T...>,
169 &invoke_typed_query_row_erased<
170 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
171 core::func_type_list<T...>{});
172 finish_typed_iter_state(query, it, state);
175 template <
typename Func,
typename... T>
176 inline void run_typed_chunk_direct_walk_cb(
177 QueryImpl& query,
const QueryInfo&, Iter& it,
void* pFunc,
const TypedQueryExecState& state) {
178 run_typed_chunk_direct_finish(query, it, *
static_cast<Func*
>(pFunc), state, core::func_type_list<T...>{});
181 template <
typename Func,
typename... T>
182 inline void run_typed_chunk_mapped_walk_cb(
183 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it,
void* pFunc,
const TypedQueryExecState& state) {
184 run_typed_chunk_mapped_finish(
185 query, queryInfo, it, *
static_cast<Func*
>(pFunc), state, core::func_type_list<T...>{});
188 template <
typename Func,
typename... T>
189 inline void each_walk_dispatch_direct(
191 const TypedQueryExecState& state, core::func_type_list<T...>) {
192 query.each_walk_inter(
193 queryInfo, entities, constraints, &func, state, &run_typed_chunk_direct_walk_cb<Func, T...>);
196 template <
typename Func,
typename... T>
197 inline void each_walk_dispatch_mapped(
199 const TypedQueryExecState& state, core::func_type_list<T...>) {
200 query.each_walk_inter(
201 queryInfo, entities, constraints, &func, state, &run_typed_chunk_mapped_walk_cb<Func, T...>);
204 template <
typename Func,
typename... T>
205 inline void run_typed_chunk_unmapped(
206 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it, Func& func,
const TypedQueryExecState& state,
207 core::func_type_list<T...> types) {
208 auto& world = *
const_cast<World*
>(queryInfo.world());
209 auto* pChunk =
const_cast<Chunk*
>(it.chunk());
210 const bool hasEntityFilters = queryInfo.has_entity_filter_terms();
212 if (!hasEntityFilters) {
213 run_typed_chunk_views(
214 &queryInfo, it, &func,
false, noop_row_done,
215 &invoke_typed_query_row_erased<
216 Func, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>, T...>,
217 &invoke_typed_query_row_erased<
218 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
220 finish_typed_chunk_state(query, world, pChunk, it.row_begin(), it.row_end(), state);
222 run_typed_chunk_views(
223 &queryInfo, it, &func,
false,
225 finish_typed_chunk_state(
226 query, world, pChunk, (uint16_t)(it.row_begin() + row), (uint16_t)(it.row_begin() + row + 1),
229 &invoke_typed_query_row_erased<
230 Func, std::tuple<decltype(std::declval<Iter&>().template sview_auto<T>())...>, T...>,
231 &invoke_typed_query_row_erased<
232 Func, std::tuple<
decltype(std::declval<Iter&>().template view_auto_any<T>())...>, T...>,
236 it.clear_touched_writes();
239 template <
typename Func,
typename... T>
240 inline void run_typed_cached_seed_runs_basic(
242 const TypedQueryExecState& state) {
244 it.init_query_state(&world, constraints,
false);
245 const Archetype* pLastArchetype =
nullptr;
246 for (
const auto& run: runs) {
247 if (run.pArchetype != pLastArchetype) {
248 it.set_archetype(run.pArchetype);
249 pLastArchetype = run.pArchetype;
252 it.set_chunk(run.pChunk, run.from, run.to);
254 run_typed_chunk_direct_finish(query, it, func, state, core::func_type_list<T...>{});
258 template <
typename Func,
typename... T>
259 inline void run_typed_cached_seed_runs_entity_init(
260 QueryImpl& query, QueryInfo& queryInfo, World& world, Constraints constraints, Func& func,
263 it.init_query_state(&world, constraints,
false);
264 const Archetype* pLastArchetype =
nullptr;
267 for (
const auto& run: runs) {
268 const auto& ec = ::gaia::ecs::fetch(world, run.pChunk->entity_view()[run.from]);
269 query.init_direct_entity_iter(queryInfo, world, ec, it, indices, termIds, pLastArchetype);
270 it.set_chunk(run.pChunk, run.from, run.to);
272 run_typed_chunk_direct_finish(query, it, func, state, core::func_type_list<T...>{});
276 template <
typename Func,
typename... T>
277 inline void run_typed_cached_seed_runs(
278 QueryImpl& query, QueryInfo& queryInfo, World& world, Constraints constraints, Func& func,
281 run_typed_cached_seed_runs_basic<Func, T...>(query, world, constraints, func, runs, state);
283 run_typed_cached_seed_runs_entity_init<Func, T...>(query, queryInfo, world, constraints, func, runs, state);
286 inline void QueryImpl::each_walk_inter(
288 const TypedQueryExecState& state,
289 void (*runChunk)(QueryImpl&,
const QueryInfo&, Iter&,
void*,
const TypedQueryExecState&)) {
290 auto& world = *queryInfo.world();
291 auto& walkData = ensure_each_walk_data();
293 it.init_query_state(&world, constraints,
false);
294 if (!walkData.cachedRuns.empty()) {
295 const auto& runs = walkData.cachedRuns;
296 const Archetype* pLastArchetype =
nullptr;
297 for (
const auto& run: runs) {
298 if (run.pArchetype != pLastArchetype) {
299 it.set_archetype(run.pArchetype);
300 pLastArchetype = run.pArchetype;
303 it.set_chunk(run.pChunk, run.from, run.to);
305 runChunk(*
this, queryInfo, it, pFunc, state);
310 const Archetype* pLastArchetype =
nullptr;
313 for (
const auto entity: entities) {
314 const auto& ec = ::gaia::ecs::fetch(world, entity);
315 init_direct_entity_iter(queryInfo, world, ec, it, indices, termIds, pLastArchetype);
316 runChunk(*
this, queryInfo, it, pFunc, state);
320 inline void finish_typed_iter_state(QueryImpl& query, Iter& it,
const TypedQueryExecState& state) {
322 query.finish_typed_iter_writes_runtime(it, state.argIds, state.writeFlags, state.argCount, state.firstWriteArg);
323 it.clear_touched_writes();
326 inline void finish_typed_chunk_state(
327 QueryImpl& query, World& world, Chunk* pChunk, uint16_t from, uint16_t to,
const TypedQueryExecState& state) {
329 query.finish_typed_chunk_writes_runtime(
330 world, pChunk, from, to, state.argIds, state.writeFlags, state.argCount, state.firstWriteArg);
333 template <
typename InvokeRow,
typename OnRowDone>
334 inline void run_typed_query_rows_runtime(
335 const QueryInfo* pQueryInfo, Iter& it, InvokeRow&& invokeRow, OnRowDone&& onRowDone) {
336 const auto cnt = it.size();
337 const bool hasEntityFilters = pQueryInfo !=
nullptr && pQueryInfo->has_entity_filter_terms();
339 if (!hasEntityFilters) {
341 invokeRow((uint32_t)i);
342 onRowDone((uint32_t)i);
347 const auto entities = it.template view<Entity>();
351 invokeRow((uint32_t)i);
352 onRowDone((uint32_t)i);
356 template <
typename Func,
typename ViewsTuple,
typename... T>
357 inline void invoke_typed_query_row(
358 Iter& it, Func& func, ViewsTuple& dataPointerTuple, uint32_t row,
bool directLocalIndex,
359 core::func_type_list<T...>) {
360 if constexpr (
sizeof...(T) > 0) {
361 if (directLocalIndex) {
363 [&](
auto&... views) {
369 [&](
auto&... views) {
370 func(views[it.template acc_index<T>(row)]...);
378 template <
typename Func,
typename ViewsTuple,
typename... T>
379 inline void invoke_typed_query_row_erased(
380 void* pFunc, Iter& it, ViewsTuple& dataPointerTuple, uint32_t row,
bool directLocalIndex) {
381 auto& func = *
static_cast<Func*
>(pFunc);
382 invoke_typed_query_row(it, func, dataPointerTuple, row, directLocalIndex, core::func_type_list<T...>{});
385 template <
typename OnRowDone,
typename ViewsTuple>
386 inline void run_typed_tuple_rows(
387 const QueryInfo* pQueryInfo, Iter& it,
void* pFunc, ViewsTuple& dataPointerTuple,
bool directLocalIndex,
388 void (*invokeRow)(
void*, Iter&, ViewsTuple&, uint32_t,
bool), OnRowDone&& onRowDone) {
389 run_typed_query_rows_runtime(
392 invokeRow(pFunc, it, dataPointerTuple, row, directLocalIndex);
394 GAIA_FWD(onRowDone));
397 template <
typename OnRowDone,
typename... T>
398 inline void run_typed_chunk_views(
399 const QueryInfo* pQueryInfo, Iter& it,
void* pFunc,
bool directViews, OnRowDone&& onRowDone,
400 void (*invokeDirectRow)(
401 void*, Iter&, std::tuple<
decltype(std::declval<Iter&>().
template sview_auto<T>())...>&, uint32_t,
bool),
402 void (*invokeMappedRow)(
403 void*, Iter&, std::tuple<
decltype(std::declval<Iter&>().
template view_auto_any<T>())...>&, uint32_t,
405 core::func_type_list<T...>) {
406 if constexpr (
sizeof...(T) > 0) {
408 auto dataPointerTuple = std::make_tuple(it.template sview_auto<T>()...);
409 run_typed_tuple_rows(pQueryInfo, it, pFunc, dataPointerTuple,
true, invokeDirectRow, GAIA_FWD(onRowDone));
411 auto dataPointerTuple = std::make_tuple(it.template view_auto_any<T>()...);
412 run_typed_tuple_rows(pQueryInfo, it, pFunc, dataPointerTuple,
false, invokeMappedRow, GAIA_FWD(onRowDone));
415 auto dataPointerTuple = std::tuple<>{};
416 run_typed_tuple_rows(
417 pQueryInfo, it, pFunc, dataPointerTuple, directViews, directViews ? invokeDirectRow : invokeMappedRow,
418 GAIA_FWD(onRowDone));
422 template <
typename ContainerOut>
423 inline void typed_arr_push(World& world, Entity entity, ContainerOut& outArray) {
424 using ContainerItemType =
typename ContainerOut::value_type;
425 if constexpr (std::is_same_v<ContainerItemType, Entity>)
426 outArray.push_back(entity);
428 auto tmp = world_direct_entity_arg<ContainerItemType>(world, entity);
429 outArray.push_back(tmp);
433 template <
bool UseFilters,
typename ContainerOut>
434 inline void run_typed_arr_rows(
435 QueryImpl& query,
const QueryInfo& queryInfo, Iter& it, ContainerOut& outArray, uint32_t changedWorldVersion,
436 uint32_t archetypeIdx,
const Archetype* pArchetype, Chunk* pChunk, uint16_t from, uint16_t to,
437 bool needsBarrierCache,
bool canUseDirectChunkEval) {
438 using ContainerItemType =
typename ContainerOut::value_type;
439 const bool barrierPasses = !needsBarrierCache || queryInfo.barrier_passes(archetypeIdx);
440 if GAIA_UNLIKELY (!query.can_process_archetype_inter(queryInfo, *pArchetype, it.constraints(), barrierPasses))
442 if GAIA_UNLIKELY (from == to)
445 GAIA_PROF_SCOPE(query::arr);
447 it.set_archetype(pArchetype);
448 it.set_chunk(pChunk, from, to);
451 const auto cnt = it.size();
455 if constexpr (UseFilters) {
460 const bool hasEntityFilters = queryInfo.has_entity_filter_terms();
461 if (canUseDirectChunkEval) {
462 const auto dataView = it.template sview_auto<ContainerItemType>();
464 auto tmp = dataView[i];
465 outArray.push_back(tmp);
470 const auto dataView = it.template view<ContainerItemType>();
471 if (!hasEntityFilters) {
473 const auto idx = it.template acc_index<ContainerItemType>(i);
474 auto tmp = dataView[idx];
475 outArray.push_back(tmp);
480 const auto entities = it.template view<Entity>();
484 const auto idx = it.template acc_index<ContainerItemType>(i);
485 auto tmp = dataView[idx];
486 outArray.push_back(tmp);
490 inline void QueryImpl::finish_typed_chunk_writes_runtime(
491 World& world, Chunk* pChunk, uint16_t from, uint16_t to,
const Entity* pArgIds,
const bool* pWriteFlags,
492 uint32_t argCnt, uint32_t firstWriteArg) {
493 if (firstWriteArg >= argCnt || from >= to)
497 uint32_t seenCnt = 0;
498 const auto entities = pChunk->entity_view();
499 const auto finish_term = [&](Entity term) {
501 if (seenTerms[i] == term)
505 seenTerms[seenCnt++] = term;
506 if (!world_is_out_of_line_component(world, term)) {
507 const auto compIdx = core::get_index(pChunk->ids_view(), term);
509 pChunk->finish_write(compIdx, from, to);
514 for (uint16_t row = from; row < to; ++row)
515 world_finish_write(world, term, entities[row]);
518 for (uint32_t i = firstWriteArg; i < argCnt; ++i) {
521 const auto term = pArgIds[i];
522 if (term != EntityBad)
527 template <
typename... T>
528 inline void QueryImpl::finish_typed_chunk_writes(World& world, Chunk* pChunk, uint16_t from, uint16_t to) {
529 TypedQueryArgMeta metas[MAX_ITEMS_IN_QUERY]{};
530 const auto argCount = init_typed_query_arg_metas(metas, world, core::func_type_list<T...>{});
531 Entity argIds[MAX_ITEMS_IN_QUERY]{};
532 bool writeFlags[MAX_ITEMS_IN_QUERY]{};
533 uint32_t firstWriteArg = argCount;
535 argIds[i] = metas[i].termId;
536 writeFlags[i] = metas[i].isWrite;
537 if (metas[i].isWrite && firstWriteArg == argCount)
538 firstWriteArg = (uint32_t)i;
540 finish_typed_chunk_writes_runtime(world, pChunk, from, to, argIds, writeFlags, argCount, firstWriteArg);
543 inline void QueryImpl::finish_typed_iter_writes_runtime(
544 Iter& it,
const Entity* pArgIds,
const bool* pWriteFlags, uint32_t argCnt, uint32_t firstWriteArg) {
545 if (firstWriteArg >= argCnt)
548 auto* pChunk =
const_cast<Chunk*
>(it.chunk());
549 if (pChunk ==
nullptr || it.row_begin() >= it.row_end())
552 auto& world = *it.world();
553 auto entities = it.entity_rows();
555 uint32_t seenCnt = 0;
556 const auto finish_term = [&](Entity term, uint32_t fieldIdx) {
558 if (seenTerms[i] == term)
562 seenTerms[seenCnt++] = term;
563 const bool isOutOfLine = world_is_out_of_line_component(world, term);
564 auto compIdx = uint8_t(0xFF);
566 compIdx = it.comp_indices()[fieldIdx];
567 else if (!isOutOfLine)
568 compIdx = (uint8_t)pChunk->comp_idx(term);
570 if (compIdx != 0xFF && !isOutOfLine) {
571 pChunk->finish_write(compIdx, it.row_begin(), it.row_end());
575 GAIA_FOR(entities.size()) {
576 world_finish_write(world, term, entities[i]);
580 for (uint32_t i = firstWriteArg; i < argCnt; ++i) {
584 Entity term = pArgIds[i];
586 term = it.term_ids()[i];
587 if (term == EntityBad)
590 finish_term(term, i);
603 template <
typename T,
typename View>
604 GAIA_NODISCARD
inline decltype(
auto) typed_direct_chunk_arg_at(View& view, uint32_t row, uint16_t from) {
605 using U =
typename actual_type_t<T>::Type;
606 if constexpr (mem::is_soa_layout_v<U>)
607 return view[from + row];
622 template <
typename Func,
typename ViewsTuple,
typename... T,
size_t... I>
623 inline void invoke_typed_direct_chunk_row(
624 Func& func, ViewsTuple& views, uint32_t row, uint16_t from, core::func_type_list<T...>,
625 std::index_sequence<I...>) {
626 func(typed_direct_chunk_arg_at<T>(std::get<I>(views), row, from)...);
637 template <
typename Func,
typename... T>
639 run_typed_direct_chunk_rows(Chunk* pChunk, uint16_t from, uint16_t to, Func& func, core::func_type_list<T...>) {
640 if constexpr (
sizeof...(T) > 0) {
641 auto views = std::make_tuple(pChunk->template sview_auto<T>(from, to)...);
642 const auto cnt = (uint32_t)(to - from);
644 invoke_typed_direct_chunk_row(
645 func, views, (uint32_t)i, from, core::func_type_list<T...>{}, std::index_sequence_for<T...>{});
647 const auto cnt = (uint32_t)(to - from);
657 inline QueryImpl::QueryPlan
674 if (hasSortedPayload || hasDepthOrderBarrier)
676 if (hasDepthOrderBarrier && !depthOrderBarrierPrunes)
678 if (depthOrderBarrierPrunes)
684 auto setDenseRange = [&]() ->
bool {
686 plan.idxFrom = cacheRange.idxFrom;
687 plan.idxTo = cacheRange.idxTo;
688 if (cacheRange.hasSelectedGroup) {
691 if (!cacheRange.valid)
694 return plan.idxFrom < plan.idxTo;
697 if (state.canUseDirectChunkEval && !canDirectEntitySeed && canDirectChunks) {
698 if (!setDenseRange()) {
709 if (canDirectEntitySeed) {
714 if (!setDenseRange()) {
721 if (hasSortedPayload) {
727 if (hasDepthOrderBarrier && depthOrderBarrierPrunes) {
739 if (hasDepthOrderBarrier) {
744 if (!canDirectChunks) {
749 if (!state.canUseDirectChunkEval) {
767 template <
bool HasFilters,
typename Func,
typename... T>
771 auto& world = *queryInfo.
world();
772 if constexpr (HasFilters) {
783 if (state.hasWriteArgs)
784 ::gaia::ecs::update_version(*m_worldVersion);
786 lock(*m_storage.
world());
788 const auto* pArchetype = cacheView[i];
793 if constexpr (HasFilters)
796 const auto& chunks = pArchetype->chunks();
797 for (
auto* pChunk: chunks) {
798 const auto from = Iter::start_index(pChunk);
799 const auto to = Iter::end_index(pChunk);
800 if GAIA_UNLIKELY (from == to)
803 if constexpr (HasFilters) {
804 if GAIA_UNLIKELY (!
match_filters(*pChunk, queryInfo, m_changedWorldVersion, indicesView))
808 GAIA_PROF_SCOPE(query_func);
809 run_typed_direct_chunk_rows(pChunk, from, to, func, types);
810 finish_typed_chunk_state(*
this, world, pChunk, from, to, state);
814 unlock(*m_storage.
world());
815 commit_cmd_buffer_st(*m_storage.
world());
816 commit_cmd_buffer_mt(*m_storage.
world());
817 m_changedWorldVersion = *m_worldVersion;
820 inline void QueryImpl::run_query_on_chunks_direct_iter(
823 auto& world = *queryInfo.
world();
827 if (plan.idxFrom >= plan.idxTo)
830 if (state.hasWriteArgs)
831 ::gaia::ecs::update_version(*m_worldVersion);
833 lock(*m_storage.
world());
836 const Archetype* pLastArchetype =
nullptr;
837 for (uint32_t i = plan.idxFrom; i < plan.idxTo; ++i) {
838 const auto* pArchetype = cacheView[i];
842 const auto& chunks = pArchetype->chunks();
843 for (
auto* pChunk: chunks) {
844 const auto from = Iter::start_index(pChunk);
845 const auto to = Iter::end_index(pChunk);
846 if GAIA_UNLIKELY (from == to)
849 GAIA_PROF_SCOPE(query_func);
850 if (pArchetype != pLastArchetype) {
851 it.set_archetype(pArchetype);
852 pLastArchetype = pArchetype;
854 it.set_chunk(pChunk, from, to);
857 runChunk(*
this, it, pFunc, state);
858 finish_typed_chunk_state(*
this, world, pChunk, from, to, state);
862 unlock(*m_storage.
world());
863 commit_cmd_buffer_st(*m_storage.
world());
864 commit_cmd_buffer_mt(*m_storage.
world());
865 m_changedWorldVersion = *m_worldVersion;
868 inline void QueryImpl::run_query_on_chunks_direct(
869 QueryInfo& queryInfo,
const QueryPlan& plan,
const TypedQueryExecState& state,
void* pFunc,
870 void (*runChunk)(QueryImpl&, Iter& it,
void*,
const TypedQueryExecState&)) {
871 auto& world = *queryInfo.world();
872 auto cacheView = queryInfo.cache_archetype_view();
873 if (plan.idxFrom >= plan.idxTo)
876 if (state.hasWriteArgs)
877 ::gaia::ecs::update_version(*m_worldVersion);
882 lock(*m_storage.
world());
884 it.init_query_state(queryInfo.world(), Constraints::EnabledOnly,
false);
885 const Archetype* pLastArchetype =
nullptr;
887 for (uint32_t i = plan.idxFrom; i < plan.idxTo; ++i) {
888 const auto* pArchetype = cacheView[i];
894 indicesView = queryInfo.indices_mapping_view(i);
896 const auto& chunks = pArchetype->chunks();
897 for (
auto* pChunk: chunks) {
898 const auto from = Iter::start_index(pChunk);
899 const auto to = Iter::end_index(pChunk);
900 if GAIA_UNLIKELY (from == to)
904 if GAIA_UNLIKELY (!
match_filters(*pChunk, queryInfo, m_changedWorldVersion, indicesView))
908 GAIA_PROF_SCOPE(query_func);
909 if (pArchetype != pLastArchetype) {
910 it.set_archetype(pArchetype);
911 pLastArchetype = pArchetype;
913 it.set_chunk(pChunk, from, to);
916 runChunk(*
this, it, pFunc, state);
917 finish_typed_chunk_state(*
this, world, pChunk, from, to, state);
921 unlock(*m_storage.
world());
922 commit_cmd_buffer_st(*m_storage.
world());
923 commit_cmd_buffer_mt(*m_storage.
world());
924 m_changedWorldVersion = *m_worldVersion;
927 template <QueryExecType ExecType>
928 inline void QueryImpl::each_inter(
929 QueryInfo& queryInfo,
const QueryPlan& plan,
void* pFunc,
const TypedQueryExecState& state,
930 void (*runDirectFastChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
931 void (*runDirectChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
932 void (*runMappedChunk)(QueryImpl&,
const QueryInfo&, Iter&,
void*,
const TypedQueryExecState&),
933 bool needsInheritedArgIds,
void (*invokeInherited)(World&, Entity,
const Entity*,
void*)) {
938 GAIA_PROF_SCOPE(query_func);
940 queryInfo, Constraints::EnabledOnly, pFunc, state, runDirectChunk, needsInheritedArgIds, invokeInherited);
944 if (state.canUseDirectChunkEval) {
945 if constexpr (ExecType == QueryExecType::Default) {
947 run_query_on_chunks_direct(queryInfo, plan, state, pFunc, runDirectFastChunk);
951 TypedDirectChunkCallback cb{
this, pFunc, &state, runDirectChunk};
952 run_query_on_chunks<ExecType, IterModeEnabled>(queryInfo, cb);
954 TypedMappedChunkCallback cb{
this, &queryInfo, pFunc, &state, runMappedChunk};
955 run_query_on_chunks<ExecType, IterModeEnabled>(queryInfo, cb);
959 template <QueryExecType ExecType,
typename Func>
960 inline void QueryImpl::each_typed_inter(QueryInfo& queryInfo, Func func) {
961 using InputArgs =
decltype(core::func_args(&Func::operator()));
963#if GAIA_ASSERT_ENABLED
964 GAIA_ASSERT(typed_query_args_match_query(queryInfo, InputArgs{}));
966 auto& world = *
const_cast<World*
>(queryInfo.world());
967 TypedQueryArgMeta metas[MAX_ITEMS_IN_QUERY]{};
968 const auto argCount = init_typed_query_arg_metas(metas, world, InputArgs{});
969 const auto state = build_typed_query_exec_state(*
this, world, queryInfo, metas, argCount);
971 if constexpr (ExecType == QueryExecType::Default) {
974 run_query_on_chunks_direct_typed<true>(queryInfo, plan, state, func, InputArgs{});
976 run_query_on_chunks_direct_typed<false>(queryInfo, plan, state, func, InputArgs{});
981 const auto runDirectFastChunk = typed_run_direct_fast_chunk_ptr<Func>(InputArgs{});
982 const auto runDirectChunk = typed_run_direct_chunk_ptr<Func>(InputArgs{});
983 const auto runMappedChunk = typed_run_mapped_chunk_ptr<Func>(InputArgs{});
984 const auto invokeInherited = typed_invoke_inherited_ptr<Func>(InputArgs{});
985 each_inter<ExecType>(
986 queryInfo, plan, &func, state, runDirectFastChunk, runDirectChunk, runMappedChunk,
987 state.needsInheritedArgIds, invokeInherited);
990 inline void QueryImpl::each_typed_erased(
991 QueryExecType execType,
void* pFunc,
const TypedQueryExecState& state,
992 void (*runDirectFastChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
993 void (*runDirectChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
994 void (*runMappedChunk)(QueryImpl&,
const QueryInfo&, Iter&,
void*,
const TypedQueryExecState&),
995 bool needsInheritedArgIds,
void (*invokeInherited)(World&, Entity,
const Entity*,
void*)) {
996 auto& queryInfo =
fetch();
1001 case QueryExecType::Parallel:
1002 each_inter<QueryExecType::Parallel>(
1003 queryInfo, plan, pFunc, state, runDirectFastChunk, runDirectChunk, runMappedChunk, needsInheritedArgIds,
1006 case QueryExecType::ParallelPerf:
1007 each_inter<QueryExecType::ParallelPerf>(
1008 queryInfo, plan, pFunc, state, runDirectFastChunk, runDirectChunk, runMappedChunk, needsInheritedArgIds,
1011 case QueryExecType::ParallelEff:
1012 each_inter<QueryExecType::ParallelEff>(
1013 queryInfo, plan, pFunc, state, runDirectFastChunk, runDirectChunk, runMappedChunk, needsInheritedArgIds,
1017 each_inter<QueryExecType::Default>(
1018 queryInfo, plan, pFunc, state, runDirectFastChunk, runDirectChunk, runMappedChunk, needsInheritedArgIds,
1024 template <
typename Func, std::enable_if_t<!detail::is_query_iter_callback_v<Func>,
int>>
1026 each(func, QueryExecType::Default);
1029 template <
typename Func, std::enable_if_t<!detail::is_query_iter_callback_v<Func>,
int>>
1031 auto& queryInfo =
fetch();
1035 case QueryExecType::Parallel:
1036 each_typed_inter<QueryExecType::Parallel>(queryInfo, func);
1038 case QueryExecType::ParallelPerf:
1039 each_typed_inter<QueryExecType::ParallelPerf>(queryInfo, func);
1041 case QueryExecType::ParallelEff:
1042 each_typed_inter<QueryExecType::ParallelEff>(queryInfo, func);
1045 each_typed_inter<QueryExecType::Default>(queryInfo, func);
1050 template <QueryExecType ExecType>
1051 inline void QueryImpl::each_iter_inter_erased(
1052 QueryInfo& queryInfo,
const QueryPlan& plan,
void* pFunc,
const TypedQueryExecState& state,
1053 void (*runDirectFastChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
1054 void (*runMappedChunk)(QueryImpl&,
const QueryInfo&, Iter&,
void*,
const TypedQueryExecState&)) {
1055 TypedIterErasedCallback cb{
this, pFunc, &state, runDirectFastChunk, runMappedChunk};
1065 if constexpr (ExecType == QueryExecType::Default) {
1067 run_query_on_chunks_direct_iter(queryInfo, plan, state, pFunc, runDirectFastChunk);
1072 run_query_on_chunks<ExecType, IterModeEnabled>(queryInfo, cb);
1075 inline void QueryImpl::each_iter_erased(
1076 QueryExecType execType,
void* pFunc,
const TypedQueryExecState& state,
1077 void (*runDirectFastChunk)(QueryImpl&, Iter&,
void*,
const TypedQueryExecState&),
1078 void (*runMappedChunk)(QueryImpl&,
const QueryInfo&, Iter&,
void*,
const TypedQueryExecState&)) {
1079 auto& queryInfo =
fetch();
1084 case QueryExecType::Parallel:
1085 each_iter_inter_erased<QueryExecType::Parallel>(
1086 queryInfo, plan, pFunc, state, runDirectFastChunk, runMappedChunk);
1088 case QueryExecType::ParallelPerf:
1089 each_iter_inter_erased<QueryExecType::ParallelPerf>(
1090 queryInfo, plan, pFunc, state, runDirectFastChunk, runMappedChunk);
1092 case QueryExecType::ParallelEff:
1093 each_iter_inter_erased<QueryExecType::ParallelEff>(
1094 queryInfo, plan, pFunc, state, runDirectFastChunk, runMappedChunk);
1097 each_iter_inter_erased<QueryExecType::Default>(
1098 queryInfo, plan, pFunc, state, runDirectFastChunk, runMappedChunk);
1103 template <
typename Func>
1105 using InputArgs =
decltype(core::func_args(&Func::operator()));
1106 auto& queryInfo =
fetch();
1108#if GAIA_ASSERT_ENABLED
1109 GAIA_ASSERT(typed_query_args_match_query(queryInfo, InputArgs{}));
1112 const auto argCount = init_typed_query_arg_metas(metas, *it.world(), InputArgs{});
1113 const auto state = build_typed_query_exec_state(*
this, *it.world(), queryInfo, metas, argCount);
1115 each_iter_dispatch(*
this, queryInfo, it, func, state, InputArgs{});
1118 inline void QueryImpl::each_iter_erased(
1122 auto& queryInfo =
fetch();
1124 if (state.canUseDirectChunkEval) {
1125 runDirectFastChunk(*
this, it, pFunc, state);
1126 finish_typed_chunk_state(
1129 runMappedChunk(*
this, queryInfo, it, pFunc, state);
1136 auto& world = *queryInfo.
world();
1137 const auto plan = direct_entity_seed_plan(world, queryInfo);
1140 auto exec_direct_entity = [&](
Entity entity) {
1144 it.set_constraints(constraints);
1145 init_direct_entity_iter(queryInfo, world, entity, it, indices, termIds);
1147 runDirectChunk(*
this, it, pFunc, state);
1150 auto exec_entity = [&](
Entity entity) {
1151 if (needsInheritedArgIds && state.hasInheritedTerms) {
1152 invokeInherited(world, entity, state.argIds, pFunc);
1153 finish_typed_query_args_by_id(world, entity, state.argIds, state.writeFlags, state.argCount);
1157 exec_direct_entity(entity);
1160 if (!hasWriteTerms && !plan.preferOrSeed) {
1161 const auto* pSeedTerm = find_direct_all_seed_term(queryInfo, plan);
1164 seedInfo.seededAllTerm = pSeedTerm->id;
1165 seedInfo.seededAllMatchKind = pSeedTerm->matchKind;
1166 seedInfo.seededFromAll =
true;
1167 if (!state.hasInheritedTerms) {
1168 const auto runs = cached_direct_seed_runs(queryInfo, *pSeedTerm, seedInfo, constraints);
1169 if (state.canUseDirectChunkEval) {
1172 const Archetype* pLastArchetype =
nullptr;
1173 for (
const auto& run: runs) {
1174 if (run.pArchetype != pLastArchetype) {
1175 it.set_archetype(run.pArchetype);
1176 pLastArchetype = run.pArchetype;
1178 it.set_chunk(run.pChunk, run.from, run.to);
1181 runDirectChunk(*
this, it, pFunc, state);
1186 const Archetype* pLastArchetype =
nullptr;
1189 for (
const auto& run: runs) {
1190 const auto& ec = ::gaia::ecs::fetch(world, run.pChunk->entity_view()[run.from]);
1191 init_direct_entity_iter(queryInfo, world, ec, it, indices, termIds, pLastArchetype);
1192 it.set_chunk(run.pChunk, run.from, run.to);
1195 runDirectChunk(*
this, it, pFunc, state);
1199 const auto entities = cached_direct_seed_chunk_entities(queryInfo, *pSeedTerm, seedInfo, constraints);
1200 for (
const auto entity: entities)
1201 exec_entity(entity);
1207 auto walk_entities = [&](
auto&& execEntity) {
1208 if (hasWriteTerms) {
1209 auto& scratch = direct_query_scratch();
1211 for (
const auto entity: scratch.entities) {
1221 if (plan.preferOrSeed) {
1229 (void)for_each_direct_all_seed(world, queryInfo, plan, constraints, [&](
Entity entity) {
1235 walk_entities(exec_entity);
1238 template <
typename Func, std::enable_if_t<!detail::is_query_walk_core_callback_v<Func>,
int>>
1240 auto& queryInfo =
fetch();
1244 using InputArgs =
decltype(core::func_args(&Func::operator()));
1245 GAIA_ASSERT(typed_query_args_match_query(queryInfo, InputArgs{}));
1250 auto& world = *queryInfo.
world();
1252 const auto argCount = init_typed_query_arg_metas(metas, world, InputArgs{});
1253 const auto state = build_typed_query_exec_state(*
this, world, queryInfo, metas, argCount);
1254 if (state.canUseDirectChunkEval) {
1255 each_walk_dispatch_direct(*
this, queryInfo, ordered, constraints, func, state, InputArgs{});
1257 each_walk_dispatch_mapped(*
this, queryInfo, ordered, constraints, func, state, InputArgs{});
1261 template <
bool UseFilters,
typename ContainerOut>
1262 inline void QueryImpl::arr_inter(QueryInfo& queryInfo, ContainerOut& outArray, Constraints constraints) {
1263 using ContainerItemType =
typename ContainerOut::value_type;
1264 if constexpr (!UseFilters) {
1266 auto& world = *queryInfo.world();
1267 const auto plan = direct_entity_seed_plan(world, queryInfo);
1268 if (plan.preferOrSeed) {
1270 typed_arr_push(world, entity, outArray);
1275 (void)for_each_direct_all_seed(world, queryInfo, plan, constraints, [&](Entity entity) {
1276 typed_arr_push(world, entity, outArray);
1284 auto& world = *queryInfo.world();
1285 const auto meta = typed_query_arg_meta<ContainerItemType>(world);
1286 const DirectChunkArgEvalDesc desc{meta.termId, meta.isEntity, meta.isPair};
1289 const bool canUseDirectChunkEval = !UseFilters && !queryInfo.has_entity_filter_terms() &&
1290 can_use_direct_chunk_term_eval_descs(world, queryInfo, &desc, 1) &&
1292 const auto cacheView = queryInfo.cache_archetype_view();
1294 const bool hasSortedArrayPayload = queryInfo.has_sorted_payload() || needsBarrierCache;
1295 const auto sortView =
1296 hasSortedArrayPayload ? queryInfo.cache_sort_view() :
decltype(queryInfo.cache_sort_view()){};
1297 if (needsBarrierCache)
1298 queryInfo.ensure_depth_order_hierarchy_barrier_cache();
1300 if (!cacheRange.valid)
1302 const auto idxFrom = cacheRange.idxFrom;
1303 const auto idxTo = cacheRange.idxTo;
1305 if (!sortView.empty()) {
1306 for (
const auto& view: sortView) {
1307 if (view.archetypeIdx < idxFrom || view.archetypeIdx >= idxTo)
1310 const bool barrierPasses = !needsBarrierCache || queryInfo.barrier_passes(view.archetypeIdx);
1312 queryInfo, *cacheView[view.archetypeIdx], constraints, barrierPasses))
1315 const auto viewFrom = view.startRow;
1316 const auto viewTo = (uint16_t)(view.startRow + view.count);
1317 uint16_t minStartRow = 0;
1318 uint16_t minEndRow = 0;
1319 chunk_effective_range(view.pChunk, constraints, needsBarrierCache, barrierPasses, minStartRow, minEndRow);
1320 const auto startRow = core::get_max(minStartRow, viewFrom);
1321 const auto endRow = core::get_min(minEndRow, viewTo);
1322 if (startRow == endRow)
1325 run_typed_arr_rows<UseFilters>(
1326 *
this, queryInfo, it, outArray, m_changedWorldVersion, view.archetypeIdx, cacheView[view.archetypeIdx],
1327 view.pChunk, startRow, endRow, needsBarrierCache, canUseDirectChunkEval);
1332 for (uint32_t i = idxFrom; i < idxTo; ++i) {
1333 auto* pArchetype = cacheView[i];
1334 const bool barrierPasses = !needsBarrierCache || queryInfo.barrier_passes(i);
1338 const auto& chunks = pArchetype->chunks();
1339 for (
auto* pChunk: chunks) {
1343 run_typed_arr_rows<UseFilters>(
1344 *
this, queryInfo, it, outArray, m_changedWorldVersion, i, pArchetype, pChunk, from, to,
1345 needsBarrierCache, canUseDirectChunkEval);
1350 template <
typename Container>
1352 const auto entCnt =
count(constraints);
1356 outArray.reserve(entCnt);
1357 auto& queryInfo =
fetch();
1360 const bool hasFilters = queryInfo.has_filters();
1362 arr_inter<true>(queryInfo, outArray, constraints);
1364 arr_inter<false>(queryInfo, outArray, constraints);
Definition span_impl.h:99
Definition archetype.h:83
Iterator for iterating entity subsets selected by Constraints. Disabled entities always precede enabl...
Definition chunk_iterator.h:1469
Definition query_info.h:100
GAIA_NODISCARD std::span< const Archetype * > cache_archetype_view() const
Returns the cached result archetypes as a span.
Definition query_info.h:2307
GAIA_NODISCARD bool has_inherited_data_payload() const
Returns true when query iteration needs cached inherited data payloads.
Definition query_info.h:1651
GAIA_NODISCARD bool has_filters() const
Returns true when the query has per-entity changed/filter terms.
Definition query_info.h:2116
GAIA_NODISCARD bool has_grouped_payload() const
Returns true when grouped-query payloads are active for this query.
Definition query_info.h:969
GAIA_NODISCARD World * world()
Returns the mutable world owning this query.
Definition query_info.h:2072
GAIA_NODISCARD bool has_sorted_payload() const
Returns true when sorted-query payloads are active for this query.
Definition query_info.h:974
GAIA_NODISCARD bool has_entity_filter_terms() const
Returns true when direct non-fragmenting terms must be rechecked per entity.
Definition query_info.h:2122
GAIA_NODISCARD QueryCtx & ctx()
Returns the mutable compiled query context.
Definition query_info.h:2092
std::span< const uint8_t > indices_mapping_view(uint32_t archetypeIdx) const
Returns a view of indices mapping for component entities in a given archetype.
Definition query_info.h:2199
void init_query_state(const World *pWorld, Constraints constraints, bool writeIm)
Initializes stable query execution state stored by the iterator.
Definition chunk_iterator.h:998
GAIA_NODISCARD uint16_t row_end() const noexcept
Returns one-past-the-end row covered by the iterator in the current chunk.
Definition chunk_iterator.h:1438
void ctx(void *pCtx)
Sets the user-owned context pointer visible through ctx().
Definition chunk_iterator.h:1095
GAIA_NODISCARD uint16_t row_begin() const noexcept
Returns the first row covered by the iterator in the current chunk.
Definition chunk_iterator.h:1433
static void chunk_effective_range(Chunk *pChunk, Constraints constraints, bool needsBarrierCache, bool barrierPasses, uint16_t &from, uint16_t &to) noexcept
Calculates the row range of a chunk after applying row constraints and depth-order barrier state.
Definition query.h:1914
void arr(Container &outArray, Constraints constraints=Constraints::EnabledOnly)
Appends all components or entities matching the query to the output array.
Definition query_typed.inl:1351
static GAIA_NODISCARD bool needs_depth_order_hierarchy_barrier_cache(const QueryInfo &queryInfo, Constraints constraints)
Checks whether the current row constraints require the depth-order hierarchy barrier cache.
Definition query.h:1903
GAIA_NODISCARD QueryPlan prepare_query_plan(const QueryInfo &queryInfo, const TypedQueryExecState &state) const
Selects the prepared execution plan for typed callbacks.
Definition query_typed.inl:658
static GAIA_NODISCARD bool match_direct_entity_constraints(const World &world, const QueryInfo &queryInfo, Entity entity, Constraints constraints)
Applies iterator-specific entity state constraints to the direct seeded path.
Definition query.h:4294
GAIA_NODISCARD bool can_use_direct_chunk_iteration_fastpath(const QueryInfo &queryInfo) const
Checks whether typed callbacks can use dense chunk iteration while preserving required cache ordering...
Definition query.h:3449
static GAIA_NODISCARD bool can_use_direct_entity_seed_eval(const QueryInfo &queryInfo)
Detects queries that can skip archetype seeding and start directly from entity-backed term indices.
Definition query.h:3941
@ Grouped
Batches carry group ids but do not require sorted slices or inherited/barrier metadata.
@ NonTrivial
Batches require non-trivial side payload such as sorted slices, inherited data, or barriers.
void for_each_direct_or_union(World &world, const QueryInfo &queryInfo, Constraints constraints, Func &&func)
Visits the deduplicated OR union for direct-seeded queries without materializing an entity seed array...
Definition query.h:4531
@ QueryPlanFlag_Sorted
The plan may need sorted cache slices; runners use them only with non-trivial payload.
Definition query.h:2090
@ QueryPlanFlag_Filtered
The query has per-chunk filters such as changed terms.
Definition query.h:2082
@ QueryPlanFlag_InheritedPayload
The query carries inherited component data into iterator payloads.
Definition query.h:2086
@ QueryPlanFlag_BarrierCache
The plan must use the depth-order hierarchy barrier cache when checking archetype/row ranges.
Definition query.h:2092
@ QueryPlanFlag_Grouped
The query uses grouped payload/ranges or grouped cache ordering.
Definition query.h:2088
@ QueryPlanFlag_EntityFilter
The query has entity-filter terms that require per-entity rechecks.
Definition query.h:2084
void each_direct_iter_inter(QueryInfo &queryInfo, Constraints constraints, Func func)
Runs an iterator-based each() callback over directly seeded entities using one-row chunk views.
Definition query.h:5037
static GAIA_NODISCARD bool match_entity_filters(const World &world, Entity entity, const QueryInfo &queryInfo)
Evaluates the entity-level terms that are not fully represented by archetype membership.
Definition query.h:4656
void each_iter(Iter &it, Func func)
Runs a typed callback against an already prepared iterator. This is used by higher-level adapters tha...
Definition query_typed.inl:1104
static GAIA_NODISCARD ExecPayloadKind exec_payload_kind(const QueryInfo &queryInfo, Constraints constraints)
Classifies the generic batch payload needed for a matched query under row constraints.
Definition query.h:2041
void each(Func func)
Iterates query matches using the default execution mode.
Definition query.h:5925
static GAIA_NODISCARD bool depth_order_hierarchy_barrier_prunes(const QueryInfo &queryInfo)
Checks whether cached depth-order barrier results can prune any matched archetype.
Definition query.h:1930
GAIA_NODISCARD QueryCacheRange selected_query_cache_range(const QueryInfo &queryInfo) const
Selects the cache range visible to this query, applying a selected group id when present.
Definition query.h:3458
static GAIA_NODISCARD bool has_depth_order_hierarchy_enabled_barrier(const QueryInfo &queryInfo)
Checks whether depth-order grouping can prune disabled hierarchy subtrees.
Definition query.h:1892
void run_query_on_chunks_direct_typed(QueryInfo &queryInfo, const QueryPlan &plan, const TypedQueryExecState &state, Func &func, core::func_type_list< T... >)
Runs the prepared direct typed row path for simple cached queries.
Definition query_typed.inl:768
static DirectEntitySeedInfo build_direct_entity_seed(const World &world, const QueryInfo &queryInfo, cnt::darray< Entity > &out)
Builds the best direct entity seed set from the smallest positive ALL term or the OR union fallback.
Definition query.h:4461
void match_all(QueryInfo &queryInfo)
Matches the query against all relevant archetypes.
Definition query.h:943
static GAIA_NODISCARD bool can_use_direct_target_eval(const QueryInfo &queryInfo)
Detects queries whose terms can be evaluated directly against concrete target entities.
Definition query.h:3959
GAIA_NODISCARD std::span< const Entity > ordered_entities_walk(QueryInfo &queryInfo, Entity relation, TravOrder order, Constraints constraints=Constraints::EnabledOnly)
Builds and caches relation traversal order for the current query result.
Definition query.h:6245
uint32_t count(Constraints constraints=Constraints::EnabledOnly)
Calculates the number of entities matching the query.
Definition query.h:6041
static GAIA_NODISCARD bool match_filters(const Chunk &chunk, const QueryInfo &queryInfo, uint32_t changedWorldVersion, std::span< const uint8_t > compIndices)
Returns whether a chunk passes the query's changed filters.
Definition query.h:1781
void each_walk(Func func, Entity relation, TravOrder order=TravOrder::Down, Constraints constraints=Constraints::EnabledOnly)
Iterates entities matching the query in a requested relation traversal order. For relation R this tre...
Definition query.h:6581
@ Sorted
Sorted payload execution that must preserve cache-provided chunk order.
@ DirectDense
Direct cached archetype/chunk iteration with query-term indices matching storage layout.
@ EntitySeed
Direct entity-seed evaluation over explicitly selected entities.
@ MappedDense
Typed dense cached archetype/chunk iteration using mapped component access. Public Iter callbacks use...
@ Empty
The selected group/range has no matching archetypes, so execution can return immediately.
@ Traversal
Traversal or inherited payload execution that requires the mapped generic path.
static GAIA_NODISCARD bool match_direct_entity_terms(const World &world, Entity entity, const QueryInfo &queryInfo, const DirectEntitySeedInfo &seedInfo)
Evaluates the remaining direct terms for a single seeded entity after the seed term itself was consum...
Definition query.h:4069
QueryInfo & fetch()
Fetches the QueryInfo object. Creates or refreshes the backing QueryInfo if needed.
Definition query.h:889
static GAIA_NODISCARD bool can_use_direct_seed_run_cache(const World &world, const QueryInfo &queryInfo, const QueryTerm &seedTerm)
Returns whether a repeated semantic or inherited seed can be cached as chunk runs.
Definition query.h:4151
GAIA_NODISCARD bool can_process_archetype_inter(const QueryInfo &queryInfo, const Archetype &archetype, Constraints constraints, int8_t barrierPasses=-1) const
Checks whether a matched archetype can be processed for the current row constraints.
Definition query.h:1970
void each_direct_inter(QueryInfo &queryInfo, Constraints constraints, void *pFunc, const TypedQueryExecState &state, void(*runDirectChunk)(QueryImpl &, Iter &, void *, const TypedQueryExecState &), bool needsInheritedArgIds, void(*invokeInherited)(World &, Entity, const Entity *, void *))
Runs a typed each() callback over directly seeded entities.
Definition query_typed.inl:1132
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
constexpr uint32_t BadIndex
Sentinel index value returned by helpers when a lookup fails.
Definition utility.h:20
Lightweight carrier for a function argument type pack.
Definition utility.h:643
uint16_t readWriteMask
Read-write mask. Bit 0 stands for component 0 in component arrays. A set bit means write access is re...
Definition query_common.h:770
Definition query_adapter_typed.inl:5
GAIA_NODISCARD World * world()
Returns the world associated with this query storage.
Definition query.h:389
Prepared query execution metadata shared by typed callbacks and public Iter callbacks.
Definition query.h:2096
uint32_t idxTo
One-past-the-end cached archetype index to process.
Definition query.h:2106
QueryPlanMode mode
Runner family selected for the current matched query cache.
Definition query.h:2098
uint32_t idxFrom
First cached archetype index to process.
Definition query.h:2104
ExecPayloadKind payloadKind
Payload layout required by generic chunk-batch runners independent of sorted-cache availability.
Definition query.h:2102
uint8_t flags
Orthogonal plan properties such as filtering, entity filters, grouping, or payload requirements.
Definition query.h:2100