Skip to content
Flecs v4.1
pipeline.h
Go to the documentation of this file.
1/**
2 * @file addons/pipeline.h
3 * @brief Pipeline module.
4 *
5 * The pipeline module provides support for running systems automatically and
6 * on multiple threads. A pipeline is a collection of tags that can be added to
7 * systems. When run, a pipeline will query for all systems that have the tags
8 * that belong to a pipeline, and run them.
9 *
10 * The module defines a number of built-in tags (EcsPreUpdate, EcsOnUpdate,
11 * EcsPostUpdate, etc.) that are registered with the built-in pipeline. The
12 * built-in pipeline is run by default when calling ecs_progress(). An
13 * application can set a custom pipeline with the ecs_set_pipeline() function.
14 */
15
16#ifdef FLECS_PIPELINE
17
18/**
19 * @defgroup c_addons_pipeline Pipeline
20 * @ingroup c_addons
21 * Pipelines order and schedule systems for execution.
22 *
23 * @{
24 */
25
26#ifndef FLECS_MODULE
27#define FLECS_MODULE
28#endif
29
30#ifndef FLECS_SYSTEM
31#define FLECS_SYSTEM
32#endif
33
34#if !defined(FLECS_OS_API_IMPL) && !defined(FLECS_NO_OS_API_IMPL)
35#define FLECS_OS_API_IMPL
36#endif
37
38#ifndef FLECS_PIPELINE_H
39#define FLECS_PIPELINE_H
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45#ifndef FLECS_LEGACY
46
47/** Convenience macro to create a forward-declared pipeline.
48 * Usage:
49 * @code
50 * ECS_DECLARE(MyPipeline);
51 * ECS_PIPELINE_DEFINE(world, MyPipeline, Update || Physics || Render)
52 * @endcode
53 */
54#define ECS_PIPELINE_DEFINE(world, id_, ...) \
55 { \
56 ecs_pipeline_desc_t desc = {0}; \
57 ecs_entity_desc_t edesc = {0}; \
58 edesc.id = id_;\
59 edesc.name = #id_;\
60 desc.entity = ecs_entity_init(world, &edesc);\
61 desc.query.expr = #__VA_ARGS__; \
62 id_ = ecs_pipeline_init(world, &desc); \
63 ecs_id(id_) = id_;\
64 ecs_assert(id_ != 0, ECS_INVALID_PARAMETER, "failed to create pipeline");\
65 } \
66 (void)id_
67
68/** Convenience macro to create a pipeline.
69 * Usage:
70 * @code
71 * ECS_PIPELINE(world, MyPipeline, Update || Physics || Render)
72 * @endcode
73 *
74 */
75#define ECS_PIPELINE(world, id, ...) \
76 ecs_entity_t id = 0, ecs_id(id) = 0; ECS_PIPELINE_DEFINE(world, id, __VA_ARGS__);\
77 (void)id;\
78 (void)ecs_id(id)
79
80/** Convenience macro to create a pipeline.
81 * See ecs_pipeline_init().
82 */
83#define ecs_pipeline(world, ...)\
84 ecs_pipeline_init(world, &(ecs_pipeline_desc_t) __VA_ARGS__ )
85
86#endif
87
88/** Pipeline descriptor, used with ecs_pipeline_init(). */
89typedef struct ecs_pipeline_desc_t {
90 /** Existing entity to associate with the pipeline (optional). */
92
93 /** The pipeline query.
94 * Pipelines are queries that are matched with system entities. Pipeline
95 * queries are the same as regular queries, which means the same query rules
96 * apply. A common mistake is to try a pipeline that matches systems in a
97 * list of phases by specifying all the phases, like:
98 * OnUpdate, OnPhysics, OnRender
99 *
100 * That however creates a query that matches entities with OnUpdate _and_
101 * OnPhysics _and_ OnRender tags, which is likely undesired. Instead, a
102 * query could use the or operator to match a system that has one of the
103 * specified phases:
104 * OnUpdate || OnPhysics || OnRender
105 *
106 * This will return the correct set of systems, but they likely won't be in
107 * the correct order. To make sure systems are returned in the correct order,
108 * two query ordering features can be used:
109 * - group_by
110 * - order_by
111 *
112 * Take a look at the system manual for a more detailed explanation of
113 * how query features can be applied to pipelines, and how the built-in
114 * pipeline query works.
115 */
118
119/** Create a custom pipeline.
120 * If the descriptor specifies an existing entity, the entity must not already
121 * be associated with a pipeline. To replace an existing pipeline on an
122 * entity, use ecs_pipeline_update().
123 *
124 * @param world The world.
125 * @param desc The pipeline descriptor.
126 * @return The pipeline, 0 if failed.
127 */
128FLECS_API
130 ecs_world_t *world,
131 const ecs_pipeline_desc_t *desc);
132
133/** Replace the pipeline query on an existing entity.
134 * Removes the pipeline currently attached to the entity and creates a new one
135 * from the descriptor.
136 *
137 * @param world The world.
138 * @param pipeline The pipeline entity to update.
139 * @param desc The pipeline descriptor.
140 * @return The pipeline entity, or 0 if the operation failed.
141 */
142FLECS_API
144 ecs_world_t *world,
145 ecs_entity_t pipeline,
146 const ecs_pipeline_desc_t *desc);
147
148/** Set a custom pipeline.
149 * This operation sets the pipeline to run when ecs_progress() is invoked.
150 *
151 * @param world The world.
152 * @param pipeline The pipeline to set.
153 */
154FLECS_API
156 ecs_world_t *world,
157 ecs_entity_t pipeline);
158
159/** Get the current pipeline.
160 * This operation gets the current pipeline.
161 *
162 * @param world The world.
163 * @return The current pipeline.
164 */
165FLECS_API
167 const ecs_world_t *world);
168
169/** Progress a world.
170 * This operation progresses the world by running all systems that are both
171 * enabled and periodic on their matching entities.
172 *
173 * An application can pass a delta_time into the function, which is the time
174 * passed since the last frame. This value is passed to systems so they can
175 * update entity values proportional to the elapsed time since their last
176 * invocation.
177 *
178 * When an application passes 0 to delta_time, ecs_progress() will automatically
179 * measure the time passed since the last frame. If an application does not use
180 * time management, it should pass a non-zero value for delta_time (1.0 is
181 * recommended). That way, no time will be wasted measuring the time.
182 *
183 * @param world The world to progress.
184 * @param delta_time The time passed since the last frame.
185 * @return false if ecs_quit() has been called, true otherwise.
186 */
187FLECS_API
189 ecs_world_t *world,
190 ecs_ftime_t delta_time);
191
192/** Run pipeline.
193 * This will run all systems in the provided pipeline. This operation may be
194 * invoked from multiple threads, and only when staging is disabled, as the
195 * pipeline manages staging and, if necessary, synchronization between threads.
196 *
197 * If 0 is provided for the pipeline ID, the default pipeline will be run (this
198 * is either the built-in pipeline or the pipeline set with ecs_set_pipeline()).
199 *
200 * When using ecs_progress(), this operation will be invoked automatically for
201 * the default pipeline (either the built-in pipeline or the pipeline set with
202 * ecs_set_pipeline()). An application may run additional pipelines.
203 *
204 * @param world The world.
205 * @param pipeline The pipeline to run.
206 * @param delta_time The delta_time to pass to systems.
207 */
208FLECS_API
210 ecs_world_t *world,
211 ecs_entity_t pipeline,
212 ecs_ftime_t delta_time);
213
214
215////////////////////////////////////////////////////////////////////////////////
216//// Threading
217////////////////////////////////////////////////////////////////////////////////
218
219/** Set number of worker threads.
220 * Setting this value to a value higher than 1 will start that many threads and
221 * will cause systems to evenly distribute matched entities across threads. The
222 * operation may be called multiple times to reconfigure the number of threads
223 * used, but never while running a system or pipeline.
224 * Calling ecs_set_threads() will also end the use of task threads set up with
225 * ecs_set_task_threads() and vice-versa.
226 *
227 * @param world The world.
228 * @param threads The number of threads to create.
229 */
230FLECS_API
232 ecs_world_t *world,
233 int32_t threads);
234
235/** Set number of worker task threads.
236 * ecs_set_task_threads() is similar to ecs_set_threads(), except threads are treated
237 * as short-lived tasks and will be created and joined around each update of the world.
238 * Creation and joining of these tasks will use the os_api_t task APIs rather than
239 * the standard thread API functions, although they may be the same if desired.
240 * This function is useful for multithreading world updates using an external
241 * asynchronous job system rather than long-running threads by providing the APIs
242 * to create tasks for your job system and then wait on their conclusion.
243 * The operation may be called multiple times to reconfigure the number of task threads
244 * used, but never while running a system or pipeline.
245 * Calling ecs_set_task_threads() will also end the use of threads set up with
246 * ecs_set_threads() and vice-versa.
247 *
248 * @param world The world.
249 * @param task_threads The number of task threads to create.
250 */
251FLECS_API
253 ecs_world_t *world,
254 int32_t task_threads);
255
256/** Return true if task thread use has been requested.
257 *
258 * @param world The world.
259 * @return Whether the world is using task threads.
260 */
261FLECS_API
263 ecs_world_t *world);
264
265////////////////////////////////////////////////////////////////////////////////
266//// Module
267////////////////////////////////////////////////////////////////////////////////
268
269/** Pipeline module import function.
270 * Usage:
271 * @code
272 * ECS_IMPORT(world, FlecsPipeline)
273 * @endcode
274 *
275 * @param world The world.
276 */
277FLECS_API
279 ecs_world_t *world);
280
281#ifdef __cplusplus
282}
283#endif
284
285#endif
286
287/** @} */
288
289#endif
FLECS_API void ecs_set_threads(ecs_world_t *world, int32_t threads)
Set number of worker threads.
FLECS_API void ecs_set_pipeline(ecs_world_t *world, ecs_entity_t pipeline)
Set a custom pipeline.
FLECS_API ecs_entity_t ecs_get_pipeline(const ecs_world_t *world)
Get the current pipeline.
FLECS_API bool ecs_progress(ecs_world_t *world, ecs_ftime_t delta_time)
Progress a world.
FLECS_API void ecs_run_pipeline(ecs_world_t *world, ecs_entity_t pipeline, ecs_ftime_t delta_time)
Run pipeline.
FLECS_API ecs_entity_t ecs_pipeline_update(ecs_world_t *world, ecs_entity_t pipeline, const ecs_pipeline_desc_t *desc)
Replace the pipeline query on an existing entity.
FLECS_API bool ecs_using_task_threads(ecs_world_t *world)
Return true if task thread use has been requested.
FLECS_API void ecs_set_task_threads(ecs_world_t *world, int32_t task_threads)
Set number of worker task threads.
FLECS_API void FlecsPipelineImport(ecs_world_t *world)
Pipeline module import function.
FLECS_API ecs_entity_t ecs_pipeline_init(ecs_world_t *world, const ecs_pipeline_desc_t *desc)
Create a custom pipeline.
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:396
struct ecs_world_t ecs_world_t
A world is the container for all ECS data and supporting features.
Definition flecs.h:440
#define ecs_ftime_t
Customizable precision for scalar time values.
Definition flecs.h:59
Pipeline descriptor, used with ecs_pipeline_init().
Definition pipeline.h:89
ecs_entity_t entity
Existing entity to associate with the pipeline (optional).
Definition pipeline.h:91
ecs_query_desc_t query
The pipeline query.
Definition pipeline.h:116
Used with ecs_query_init().
Definition flecs.h:1316