Monado OpenXR Runtime
comp_render.h
Go to the documentation of this file.
1// Copyright 2019-2024, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Compositor render implementation.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
8 * @ingroup comp_util
9 */
10
11#pragma once
12
13#include "xrt/xrt_defines.h"
14#include "xrt/xrt_vulkan_includes.h" // IWYU pragma: keep
15
17#include "util/u_misc.h"
18
19#include <assert.h>
20
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26struct comp_layer;
27struct render_compute;
28struct render_gfx;
30
31
32/*!
33 * @defgroup comp_render
34 * @brief Renders, aka "layer squashers" and distortion application.
35 *
36 * Two parallel implementations of the render module exist:
37 *
38 * - one uses graphics shaders (aka GFX, @ref comp_render_gfx, @ref comp_render_gfx.c)
39 * - the other uses compute shaders (aka CS, @ref comp_render_cs, @ref comp_render_cs.c)
40 *
41 * Their abilities are effectively equivalent, although the graphics version disregards depth
42 * data, while the compute shader does use it somewhat.
43 *
44 * @note In general this module requires that swapchains in your supplied @ref comp_layer layers
45 * implement @ref comp_swapchain in addition to just @ref xrt_swapchain.
46 */
47
48/*
49 *
50 * Input data struct.
51 *
52 */
53
54/*!
55 * @name Input data structs
56 * @{
57 */
58
59/*!
60 * The input data needed for a single view, shared between both GFX and CS
61 * paths.
62 *
63 * To fully render a single view two "rendering" might be needed, the
64 * first being the layer squashing, and the second is the distortion step. The
65 * target for the layer squashing is referred to as "layer" or "scratch" and
66 * prefixed with `layer` if needs be. The other final step is referred to as
67 * "distortion target" or just "target", and is prefixed with `target`.
68 *
69 * @ingroup comp_render
70 */
72{
73 //! New world pose of this view.
75
76 //! New eye pose of this view.
78
79 /*!
80 * New fov of this view, used for the layer scratch image. Needs to
81 * match distortion parameters if distortion is used.
82 */
83 struct xrt_fov fov;
84
85 /*!
86 * The layer image for this view (aka scratch image),
87 * used for barrier operations.
88 */
89 VkImage image;
90
91 /*!
92 * View into layer image (aka scratch image),
93 * used for both GFX (read/write) and CS (read) paths.
94 */
95 VkImageView srgb_view;
96
97 /*!
98 * Pre-view layer target viewport_data (where in the image we should
99 * render the view).
100 */
102
103 /*!
104 * When sampling from the layer image (aka scratch image), how should we
105 * transform it to get to the pixels correctly.
106 */
108
109 //! Go from UV to tanangle for the target, this needs to match @p fov.
111
112 // Distortion target viewport data (aka target).
113 struct render_viewport_data target_viewport_data;
114
115 struct
116 {
117 //! Per-view layer target resources.
119
120 //! Distortion target vertex rotation information.
122 } gfx;
123
124 struct
125 {
126 //! Only used on compute path.
127 VkImageView unorm_view;
128 } cs;
129};
130
131/*!
132 * The input data needed for a complete layer squashing distortion rendering
133 * to a target. This struct is shared between GFX and CS paths.
134 *
135 * @ingroup comp_render
136 */
138{
139 struct comp_render_view_data views[XRT_MAX_VIEWS];
140
141 //! The number of views currently in this dispatch data.
142 uint32_t view_count;
143
144 //! Fast path can be disabled for mirroing so needs to be an argument.
146
147 //! Very often true, can be disabled for debugging.
149
150 //! Members used only by GFX @ref comp_render_gfx
151 struct
152 {
153 //! The resources needed for the target.
156
157 //! Members used only by CS @ref comp_render_cs
158 struct
159 {
160 //! Target image for distortion, used for barrier.
162
163 //! Target image view for distortion.
164 VkImageView target_unorm_view;
165 } cs;
166};
167
168/*!
169 * Shared implementation setting up common view params between GFX and CS.
170 *
171 * Private implementation method, do not use outside of more-specific add_view calls!
172 *
173 * @param data Common render dispatch data, will be updated
174 * @param world_pose New world pose of this view.
175 * Populates @ref comp_render_view_data::world_pose
176 * @param eye_pose New eye pose of this view
177 * Populates @ref comp_render_view_data::eye_pose
178 * @param fov Assigned to fov in the view data, and used to compute @ref comp_render_view_data::target_pre_transform
179 * Populates @ref comp_render_view_data::fov
180 * @param layer_viewport_data Where in the image to render the view
181 * Populates @ref comp_render_view_data::layer_viewport_data
182 * @param layer_norm_rect How to transform when sampling from the scratch image.
183 * Populates @ref comp_render_view_data::layer_norm_rect
184 * @param image Scratch image for this view
185 * Populates @ref comp_render_view_data::image
186 * @param srgb_view SRGB image view into the scratch image
187 * Populates @ref comp_render_view_data::srgb_view
188 * @param target_viewport_data Distortion target viewport data (aka target)
189 * Populates @ref comp_render_view_data::target_viewport_data
190
191 * @return Pointer to the @ref comp_render_view_data we have been populating, for additional setup.
192 */
193static inline struct comp_render_view_data *
195 const struct xrt_pose *world_pose,
196 const struct xrt_pose *eye_pose,
197 const struct xrt_fov *fov,
200 VkImage image,
201 VkImageView srgb_view,
202 const struct render_viewport_data *target_viewport_data)
203{
204 uint32_t i = data->view_count++;
205
206 assert(i < ARRAY_SIZE(data->views));
207
208 struct comp_render_view_data *view = &data->views[i];
209
211
212 view->world_pose = *world_pose;
213 view->eye_pose = *eye_pose;
214 view->fov = *fov;
215 view->image = image;
216 view->srgb_view = srgb_view;
219 view->target_viewport_data = *target_viewport_data;
220
221 return view;
222}
223
224/*! @} */
225
226/*
227 *
228 * Gfx functions.
229 *
230 */
231
232/*!
233 *
234 * @defgroup comp_render_gfx
235 *
236 * GFX renderer control and dispatch - uses graphics shaders.
237 *
238 * Depends on the common @ref comp_render_dispatch_data, as well as the resources
239 * @ref render_gfx_target_resources (often called `rtr`), and @ref render_gfx.
240 *
241 * @ingroup comp_render
242 * @{
243 */
244
245/*!
246 * Initialize structure for use of the GFX renderer.
247 *
248 * @param[out] data Common render dispatch data. Will be zeroed and initialized.
249 * @param rtr GFX-specific resources for the entire frameedg. Must be populated before call.
250 * @param fast_path Whether we will use the "fast path" avoiding layer squashing.
251 * @param do_timewarp Whether timewarp (reprojection) will be performed.
252 */
253static inline void
256 bool fast_path,
257 bool do_timewarp)
258{
259 U_ZERO(data);
260
261 data->fast_path = fast_path;
262 data->do_timewarp = do_timewarp;
263 data->gfx.rtr = rtr;
264}
265
266/*!
267 * Add view to the common data, as required by the GFX renderer.
268 *
269 * @param[in,out] data Common render dispatch data, will be updated
270 * @param world_pose New world pose of this view.
271 * Populates @ref comp_render_view_data::world_pose
272 * @param eye_pose New eye pose of this view
273 * Populates @ref comp_render_view_data::eye_pose
274 * @param fov Assigned to fov in the view data, and used to
275 * compute @ref comp_render_view_data::target_pre_transform - also
276 * populates @ref comp_render_view_data::fov
277 * @param rtr Will be associated with this view. GFX-specific
278 * @param layer_viewport_data Where in the image to render the view
279 * Populates @ref comp_render_view_data::layer_viewport_data
280 * @param layer_norm_rect How to transform when sampling from the scratch image.
281 * Populates @ref comp_render_view_data::layer_norm_rect
282 * @param image Scratch image for this view
283 * Populates @ref comp_render_view_data::image
284 * @param srgb_view SRGB image view into the scratch image
285 * Populates @ref comp_render_view_data::srgb_view
286 * @param vertex_rot
287 * @param target_viewport_data Distortion target viewport data (aka target)
288 * Populates @ref comp_render_view_data::target_viewport_data
289 */
290static inline void
292 const struct xrt_pose *world_pose,
293 const struct xrt_pose *eye_pose,
294 const struct xrt_fov *fov,
298 VkImage image,
299 VkImageView srgb_view,
300 const struct xrt_matrix_2x2 *vertex_rot,
301 const struct render_viewport_data *target_viewport_data)
302{
304 data, //
305 world_pose, //
306 eye_pose, //
307 fov, //
310 image, //
311 srgb_view, //
312 target_viewport_data);
313
314 // TODO why is the one in data not used instead
315 view->gfx.rtr = rtr;
316 view->gfx.vertex_rot = *vertex_rot;
317}
318
319/*!
320 * Writes the needed commands to the @ref render_gfx to do a full composition with distortion.
321 *
322 * Takes a set of layers, new device poses, scratch
323 * images with associated @ref render_gfx_target_resources and writes the needed
324 * commands to the @ref render_gfx to do a full composition with distortion.
325 * The scratch images are optionally used to squash layers should it not be
326 * possible to do a @p comp_render_dispatch_data::fast_path. Will use the render
327 * passes of the targets which set the layout.
328 *
329 * The render passes of @p comp_render_dispatch_data::views::rtr must be created
330 * with a final_layout of `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` or there will
331 * be validation errors.
332 *
333 * Expected layouts:
334 *
335 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
336 * - Scratch images: Any (as per the @ref render_gfx_render_pass)
337 * - Target image: Any (as per the @ref render_gfx_render_pass)
338 *
339 * After call layouts:
340 *
341 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
342 * - Scratch images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
343 * - Target image: What the render pass of @p rtr specifies.
344 *
345 * @note Swapchains in the @p layers must implement @ref comp_swapchain in
346 * addition to just @ref xrt_swapchain, as this function downcasts to @ref comp_swapchain !
347 *
348 * @param rr GFX render object
349 * @param[in] layers Layers to render, see note.
350 * @param[in] layer_count Number of elements in @p layers array.
351 * @param[in] d Common render dispatch data
352 */
353void
355 const struct comp_layer *layers,
356 const uint32_t layer_count,
357 const struct comp_render_dispatch_data *d);
358
359/* end of comp_render_gfx group */
360
361/*! @} */
362
363
364/*
365 *
366 * CS functions.
367 *
368 */
369
370/*!
371 *
372 * @defgroup comp_render_cs
373 *
374 * CS renderer control and dispatch - uses compute shaders
375 *
376 * Depends on @ref render_compute (often called `crc`)
377 *
378 * @ingroup comp_render
379 * @{
380 */
381
382/*!
383 * Initialize structure for use of the CS renderer.
384 *
385 * @param data Common render dispatch data. Will be zeroed and initialized.
386 * @param target_image Image to render into
387 * @param target_unorm_view Corresponding image view
388 * @param fast_path Whether we will use the "fast path" avoiding layer squashing.
389 * @param do_timewarp Whether timewarp (reprojection) will be performed.
390 */
391static inline void
393 VkImage target_image,
394 VkImageView target_unorm_view,
395 bool fast_path,
396 bool do_timewarp)
397{
398 U_ZERO(data);
399
400 data->fast_path = fast_path;
401 data->do_timewarp = do_timewarp;
402
403 data->cs.target_image = target_image;
404 data->cs.target_unorm_view = target_unorm_view;
405}
406
407/*!
408 * Add view to the common data, as required by the CS renderer.
409 *
410 * @param[in,out] data Common render dispatch data, will be updated
411 * @param world_pose New world pose of this view.
412 * Populates @ref comp_render_view_data::world_pose
413 * @param eye_pose New eye pose of this view
414 * Populates @ref comp_render_view_data::eye_pose
415 * @param fov Assigned to fov in the view data, and used to compute @ref comp_render_view_data::target_pre_transform
416 * Populates @ref comp_render_view_data::fov
417 * @param layer_viewport_data Where in the image to render the view
418 * Populates @ref comp_render_view_data::layer_viewport_data
419 * @param layer_norm_rect How to transform when sampling from the scratch image.
420 * Populates @ref comp_render_view_data::layer_norm_rect
421 * @param image Scratch image for this view
422 * Populates @ref comp_render_view_data::image
423 * @param srgb_view SRGB image view into the scratch image
424 * Populates @ref comp_render_view_data::srgb_view
425 * @param unorm_view UNORM image view into the scratch image, CS specific
426 * @param target_viewport_data Distortion target viewport data (aka target)
427 * Populates @ref comp_render_view_data::target_viewport_data
428 */
429static inline void
431 const struct xrt_pose *world_pose,
432 const struct xrt_pose *eye_pose,
433 const struct xrt_fov *fov,
436 VkImage image,
437 VkImageView srgb_view,
438 VkImageView unorm_view,
439 const struct render_viewport_data *target_viewport_data)
440{
442 data, //
443 world_pose, //
444 eye_pose, //
445 fov, //
448 image, //
449 srgb_view, //
450 target_viewport_data);
451
452 view->cs.unorm_view = unorm_view;
453}
454
455/*!
456 * Dispatch the layer squasher for a single view.
457 *
458 * All source layer images and target image needs to be in the correct image
459 * layout, no barrier is inserted at all. The @p view_index argument is needed
460 * to grab a pre-allocated UBO from the @ref render_resources and to correctly
461 * select left/right data from various layers.
462 *
463 * Expected layouts:
464 *
465 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
466 * - Target images: `VK_IMAGE_LAYOUT_GENERAL`
467 *
468 * @note Swapchains in the @p layers must implement @ref comp_swapchain in
469 * addition to just @ref xrt_swapchain, as this function downcasts to @ref comp_swapchain !
470 *
471 * @param crc Compute renderer object
472 * @param view_index Index of the view
473 * @param layers Layers to render, see note.
474 * @param layer_count Number of elements in @p layers array.
475 * @param pre_transform
476 * @param world_pose
477 * @param eye_pose
478 * @param target_image
479 * @param target_image_view
480 * @param target_view
481 * @param do_timewarp
482 */
483void
485 uint32_t view_index,
486 const struct comp_layer *layers,
487 const uint32_t layer_count,
488 const struct xrt_normalized_rect *pre_transform,
489 const struct xrt_pose *world_pose,
490 const struct xrt_pose *eye_pose,
491 const VkImage target_image,
492 const VkImageView target_image_view,
493 const struct render_viewport_data *target_view,
494 bool do_timewarp);
495
496/*!
497 * Dispatch the layer squasher, on any number of views.
498 *
499 * All source layer images needs to be in the correct image layout, no barrier
500 * is inserted for them. The target images are barriered from undefined to general
501 * so they can be written to, then to the laying defined by @p transition_to.
502 *
503 * Expected layouts:
504 *
505 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
506 * - Target images: Any
507 *
508 * After call layouts:
509 *
510 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
511 * - Target images: @p transition_to
512 *
513 * @note Swapchains in the @p layers must implement @ref comp_swapchain in
514 * addition to just @ref xrt_swapchain, as this function downcasts to @ref comp_swapchain !
515 *
516 * @param crc Compute renderer object
517 * @param[in] layers Layers to render, see note.
518 * @param[in] layer_count Number of elements in @p layers array.
519 * @param[in] d Common render dispatch data
520 * @param[in] transition_to Desired image layout for target images
521 */
522void
524 const struct comp_layer *layers,
525 const uint32_t layer_count,
526 const struct comp_render_dispatch_data *d,
527 VkImageLayout transition_to);
528
529/*!
530 * Write commands to @p crc to do a full composition with distortion.
531 *
532 * Helper function that takes a set of layers, new device poses, a scratch
533 * images and writes the needed commands to the @ref render_compute to do a full
534 * composition with distortion. The scratch images are optionally used to squash
535 * layers should it not be possible to do a fast_path. Will insert barriers to
536 * change the scratch images and target images to the needed layout.
537 *
538 *
539 * Expected layouts:
540 *
541 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
542 * - Scratch images: Any
543 * - Target image: Any
544 *
545 * After call layouts:
546 *
547 * - Layer images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
548 * - Scratch images: `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL`
549 * - Target image: `VK_IMAGE_LAYOUT_PRESENT_SRC_KHR`
550 *
551 * @note Swapchains in the @p layers must implement @ref comp_swapchain in
552 * addition to just @ref xrt_swapchain, as this function downcasts to @ref comp_swapchain !
553 *
554 * @param crc Compute renderer object
555 * @param[in] layers Layers to render, see note.
556 * @param[in] layer_count Number of elements in @p layers array.
557 * @param[in] d Common render dispatch data
558 *
559 */
560void
562 const struct comp_layer *layers,
563 const uint32_t layer_count,
564 const struct comp_render_dispatch_data *d);
565
566/* end of comp_render_cs group */
567/*! @} */
568
569#ifdef __cplusplus
570}
571#endif
static struct comp_render_view_data * comp_render_dispatch_add_view(struct comp_render_dispatch_data *data, const struct xrt_pose *world_pose, const struct xrt_pose *eye_pose, const struct xrt_fov *fov, const struct render_viewport_data *layer_viewport_data, const struct xrt_normalized_rect *layer_norm_rect, VkImage image, VkImageView srgb_view, const struct render_viewport_data *target_viewport_data)
Shared implementation setting up common view params between GFX and CS.
Definition: comp_render.h:194
#define U_ZERO(PTR)
Zeroes the correct amount of memory based on the type pointed-to by the argument.
Definition: u_misc.h:68
void comp_render_cs_layers(struct render_compute *crc, const struct comp_layer *layers, const uint32_t layer_count, const struct comp_render_dispatch_data *d, VkImageLayout transition_to)
Dispatch the layer squasher, on any number of views.
Definition: comp_render_cs.c:661
static void comp_render_cs_add_view(struct comp_render_dispatch_data *data, const struct xrt_pose *world_pose, const struct xrt_pose *eye_pose, const struct xrt_fov *fov, const struct render_viewport_data *layer_viewport_data, const struct xrt_normalized_rect *layer_norm_rect, VkImage image, VkImageView srgb_view, VkImageView unorm_view, const struct render_viewport_data *target_viewport_data)
Add view to the common data, as required by the CS renderer.
Definition: comp_render.h:430
static void comp_render_cs_initial_init(struct comp_render_dispatch_data *data, VkImage target_image, VkImageView target_unorm_view, bool fast_path, bool do_timewarp)
Initialize structure for use of the CS renderer.
Definition: comp_render.h:392
void comp_render_cs_dispatch(struct render_compute *crc, const struct comp_layer *layers, const uint32_t layer_count, const struct comp_render_dispatch_data *d)
Write commands to crc to do a full composition with distortion.
Definition: comp_render_cs.c:708
void comp_render_cs_layer(struct render_compute *crc, uint32_t view_index, const struct comp_layer *layers, const uint32_t layer_count, const struct xrt_normalized_rect *pre_transform, const struct xrt_pose *world_pose, const struct xrt_pose *eye_pose, const VkImage target_image, const VkImageView target_image_view, const struct render_viewport_data *target_view, bool do_timewarp)
Dispatch the layer squasher for a single view.
Definition: comp_render_cs.c:490
static void comp_render_gfx_initial_init(struct comp_render_dispatch_data *data, struct render_gfx_target_resources *rtr, bool fast_path, bool do_timewarp)
Initialize structure for use of the GFX renderer.
Definition: comp_render.h:254
void comp_render_gfx_dispatch(struct render_gfx *rr, const struct comp_layer *layers, const uint32_t layer_count, const struct comp_render_dispatch_data *d)
Writes the needed commands to the render_gfx to do a full composition with distortion.
Definition: comp_render_gfx.c:816
static void comp_render_gfx_add_view(struct comp_render_dispatch_data *data, const struct xrt_pose *world_pose, const struct xrt_pose *eye_pose, const struct xrt_fov *fov, struct render_gfx_target_resources *rtr, const struct render_viewport_data *layer_viewport_data, const struct xrt_normalized_rect *layer_norm_rect, VkImage image, VkImageView srgb_view, const struct xrt_matrix_2x2 *vertex_rot, const struct render_viewport_data *target_viewport_data)
Add view to the common data, as required by the GFX renderer.
Definition: comp_render.h:291
void render_calc_uv_to_tangent_lengths_rect(const struct xrt_fov *fov, struct xrt_normalized_rect *out_rect)
This function constructs a transformation in the form of a normalized rect that lets you go from a UV...
Definition: render_util.c:127
The NEW compositor rendering code header.
A single layer in a comp_layer_accum.
Definition: comp_layer_accum.h:36
The input data needed for a complete layer squashing distortion rendering to a target.
Definition: comp_render.h:138
uint32_t view_count
The number of views currently in this dispatch data.
Definition: comp_render.h:142
struct render_gfx_target_resources * rtr
The resources needed for the target.
Definition: comp_render.h:154
bool do_timewarp
Very often true, can be disabled for debugging.
Definition: comp_render.h:148
struct comp_render_dispatch_data::@111 cs
Members used only by CS Comp_render_cs.
VkImage target_image
Target image for distortion, used for barrier.
Definition: comp_render.h:161
VkImageView target_unorm_view
Target image view for distortion.
Definition: comp_render.h:164
bool fast_path
Fast path can be disabled for mirroing so needs to be an argument.
Definition: comp_render.h:145
struct comp_render_dispatch_data::@110 gfx
Members used only by GFX Comp_render_gfx.
The input data needed for a single view, shared between both GFX and CS paths.
Definition: comp_render.h:72
VkImageView unorm_view
Only used on compute path.
Definition: comp_render.h:127
VkImageView srgb_view
View into layer image (aka scratch image), used for both GFX (read/write) and CS (read) paths.
Definition: comp_render.h:95
struct xrt_fov fov
New fov of this view, used for the layer scratch image.
Definition: comp_render.h:83
struct render_viewport_data layer_viewport_data
Pre-view layer target viewport_data (where in the image we should render the view).
Definition: comp_render.h:101
struct xrt_matrix_2x2 vertex_rot
Distortion target vertex rotation information.
Definition: comp_render.h:121
struct xrt_pose world_pose
New world pose of this view.
Definition: comp_render.h:74
struct render_gfx_target_resources * rtr
Per-view layer target resources.
Definition: comp_render.h:118
struct xrt_pose eye_pose
New eye pose of this view.
Definition: comp_render.h:77
VkImage image
The layer image for this view (aka scratch image), used for barrier operations.
Definition: comp_render.h:89
struct xrt_normalized_rect layer_norm_rect
When sampling from the layer image (aka scratch image), how should we transform it to get to the pixe...
Definition: comp_render.h:107
struct xrt_normalized_rect target_pre_transform
Go from UV to tanangle for the target, this needs to match fov.
Definition: comp_render.h:110
A compute rendering is used to create command buffers needed to do one frame of compositor rendering ...
Definition: render_interface.h:1106
Each rendering (render_gfx) render to one or more targets (render_gfx_target_resources),...
Definition: render_interface.h:775
A rendering is used to create command buffers needed to do one frame of compositor rendering,...
Definition: render_interface.h:823
The pure data information about a view that the renderer is rendering to.
Definition: render_interface.h:677
Describes a projection matrix fov.
Definition: xrt_defines.h:486
A tightly packed 2x2 matrix of floats.
Definition: xrt_defines.h:513
Normalized image rectangle, coordinates and size in 0 .
Definition: xrt_defines.h:453
A pose composed of a position and orientation.
Definition: xrt_defines.h:465
Very small misc utils.
#define ARRAY_SIZE(a)
Array size helper.
Definition: xrt_compiler.h:30
Common defines and enums for XRT.
Include all of the Vulkan headers in one place, and cope with any "messy" includes implied by it.