The open source OpenXR runtime
1// Copyright 2019-2024, Collabora, Ltd.
2// Copyright 2024-2025, NVIDIA CORPORATION.
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Helper implementation for native compositors.
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
9 * @ingroup comp_util
10 */
11
12#pragma once
13
14#include "util/u_native_images_debug.h"
15
16#include "vk/vk_helpers.h"
17
18#include "render/render_interface.h"
19
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25
26/*
27 *
28 * Defines.
29 *
30 */
31
32//! The number of images for each view, works like a swapchain.
33#define COMP_SCRATCH_NUM_IMAGES (4)
34
35
36/*
37 *
38 * Common for handling indices.
39 *
40 */
41
42/*!
43 * Small helper struct to deal with indices.
44 *
45 * @ingroup comp_util
46 */
47struct comp_scratch_indices
48{
49 uint32_t current;
50
51 uint32_t last;
52};
53
54
55/*
56 *
57 * Single view images.
58 *
59 */
60
61/*!
62 * Holds scratch images for a single view, designed to work with render code.
63 * Also manages @ref xrt_image_native and @ref u_native_images_debug to
64 * facilitate easy debugging.
65 *
66 * @ingroup comp_util
67 */
68struct comp_scratch_single_images
69{
70 //! Images used when rendering.
71 struct render_scratch_color_image images[COMP_SCRATCH_NUM_IMAGES];
72
73 //! To connect to the debug UI.
74 struct u_native_images_debug unid;
75
76 //! Exposed via @ref unid.
77 struct xrt_swapchain_create_info info;
78
79 //! Exposed via @ref unid.
80 struct xrt_image_native native_images[COMP_SCRATCH_NUM_IMAGES];
81
82 //! Keeping track of indices.
83 struct comp_scratch_indices indices;
84
85 //! Process unique id, used for caching.
86 xrt_limited_unique_id_t limited_unique_id;
87};
88
89/*!
90 * Init the struct, this function must be called before calling any other
91 * function on this struct, or variable tracking setup on @p unid. Zero init is
92 * not enough as it has a mutex in it and has native handles which on some
93 * platforms zero is a valid handle.
94 *
95 * @public @memberof comp_scratch_single_images
96 *
97 * @ingroup comp_util
98 */
99void
100comp_scratch_single_images_init(struct comp_scratch_single_images *cssi);
101
102/*!
103 * Ensure that the scratch images are allocated and match @p extent size, and
104 * @p format.
105 *
106 * @public @memberof comp_scratch_single_images
107 *
108 * @ingroup comp_util
109 */
110bool
111comp_scratch_single_images_ensure(struct comp_scratch_single_images *cssi,
112 struct vk_bundle *vk,
113 VkExtent2D extent,
114 const VkFormat format);
115
116/*!
117 * Ensure that the scratch images are allocated and match @p extent size,
118 * the formats it will get is 8bit SRGB formats.
119 *
120 * @public @memberof comp_scratch_single_images
121 *
122 * @ingroup comp_util
123 */
124bool
125comp_scratch_single_images_ensure_mutable(struct comp_scratch_single_images *cssi,
126 struct vk_bundle *vk,
127 VkExtent2D extent);
128
129/*!
130 * Free all images allocated, @p init must be called before calling this
131 * function, is safe to call without any image allocated.
132 *
133 * @public @memberof comp_scratch_single_images
134 *
135 * @ingroup comp_util
136 */
137void
138comp_scratch_single_images_free(struct comp_scratch_single_images *cssi, struct vk_bundle *vk);
139
140/*!
141 * Get the next free image, after this function has been called you must call
142 * either @p done or @p discard before calling any other function.
143 *
144 * @public @memberof comp_scratch_single_images
145 *
146 * @ingroup comp_util
147 */
148void
149comp_scratch_single_images_get(struct comp_scratch_single_images *cssi, uint32_t *out_index);
150
151/*!
152 * Get the image for the given index.
153 *
154 * @public @memberof comp_scratch_single_images
155 *
156 * @ingroup comp_util
157 */
158static inline VkImage
159comp_scratch_single_images_get_image(struct comp_scratch_single_images *cssi, uint32_t index)
160{
161 return cssi->images[index].image;
162}
163
164/*!
165 * Get the image view for sampling, it will apply any automatic linearization,
166 * aka sRGB gamma curve correction.
167 *
168 * @public @memberof comp_scratch_single_images
169 *
170 * @ingroup comp_util
171 */
172static inline VkImageView
173comp_scratch_single_images_get_sample_view(struct comp_scratch_single_images *cssi, uint32_t index)
174{
175 struct render_scratch_color_image *rsci = &cssi->images[index];
176
177 VkImageView view = rsci->srgb_view;
178 if (view != VK_NULL_HANDLE) {
179 return view;
180 }
181
182 // Fallback to unorm view.
183 return rsci->unorm_view;
184}
185
186/*!
187 * Get the image view for storage or direct value, no linearization will be
188 * done.
189 *
190 * @public @memberof comp_scratch_single_images
191 *
192 * @ingroup comp_util
193 */
194static inline VkImageView
195comp_scratch_single_images_get_storage_view(struct comp_scratch_single_images *cssi, uint32_t index)
196{
197 struct render_scratch_color_image *rsci = &cssi->images[index];
198
199 // Always the storage view.
200 return rsci->unorm_view;
201}
202
203/*!
204 * After calling @p get and rendering to the image you call this function to
205 * signal that you are done with this function, the GPU work needs to be fully
206 * completed before calling done.
207 *
208 * @public @memberof comp_scratch_single_images
209 *
210 * @ingroup comp_util
211 */
212void
213comp_scratch_single_images_done(struct comp_scratch_single_images *cssi);
214
215/*!
216 * Discard a @p get call, this clears the image debug part causing no image to
217 * be shown in the debug UI.
218 *
219 * @public @memberof comp_scratch_single_images
220 *
221 * @ingroup comp_util
222 */
223void
224comp_scratch_single_images_discard(struct comp_scratch_single_images *cssi);
225
226/*!
227 * Clears the debug output, this causes nothing to be shown in the debug UI.
228 *
229 * @public @memberof comp_scratch_single_images
230 *
231 * @ingroup comp_util
232 */
233void
234comp_scratch_single_images_clear_debug(struct comp_scratch_single_images *cssi);
235
236/*!
237 * Destroys scratch image struct, if any images has been allocated must call
238 * @p free before as this function only destroys the mutex, and the @p unid must
239 * no longer be tracked.
240 *
241 * @public @memberof comp_scratch_single_images
242 *
243 * @ingroup comp_util
244 */
245void
246comp_scratch_single_images_destroy(struct comp_scratch_single_images *cssi);
247
248
249/*
250 *
251 * Stereo.
252 *
253 */
254
255/*!
256 * Holds scartch images for a stereo views, designed to work with render code.
257 * Also manages @ref xrt_image_native and @ref u_native_images_debug to
258 * facilitate easy debugging.
259 *
260 * @ingroup comp_util
261 */
262struct comp_scratch_stereo_images
263{
264 struct render_scratch_images rsis[COMP_SCRATCH_NUM_IMAGES];
265
266 struct xrt_swapchain_create_info info;
267
268 //! Keeping track of indices.
269 struct comp_scratch_indices indices;
270
271 struct
272 {
273 //! Debug output for each view.
274 struct u_native_images_debug unid;
275
276 //! Count always equals to the number of rsis.
277 struct xrt_image_native native_images[COMP_SCRATCH_NUM_IMAGES];
278 } views[2];
279
280 //! Process unique id, used for caching.
281 xrt_limited_unique_id_t limited_unique_id;
282};
283
284void
285comp_scratch_stereo_images_init(struct comp_scratch_stereo_images *cssi);
286
287bool
288comp_scratch_stereo_images_ensure(struct comp_scratch_stereo_images *cssi, struct vk_bundle *vk, VkExtent2D extent);
289
290void
291comp_scratch_stereo_images_free(struct comp_scratch_stereo_images *cssi, struct vk_bundle *vk);
292
293void
294comp_scratch_stereo_images_get(struct comp_scratch_stereo_images *cssi, uint32_t *out_index);
295
296void
297comp_scratch_stereo_images_done(struct comp_scratch_stereo_images *cssi);
298
299void
300comp_scratch_stereo_images_discard(struct comp_scratch_stereo_images *cssi);
301
302void
303comp_scratch_stereo_images_clear_debug(struct comp_scratch_stereo_images *cssi);
304
305void
306comp_scratch_stereo_images_destroy(struct comp_scratch_stereo_images *cssi);
307
308
309#ifdef __cplusplus
310}
311#endif