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 Higher level interface for rendering a frame.
7 * @author Jakob Bornecrantz <tbornecrantz@nvidia.com>
8 * @author Christoph Haag <christoph.haag@collabora.com>
9 * @author Fernando Velazquez Innella <finnella@magicleap.com>
10 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
11 * @ingroup comp_util
12 */
13
14#include "comp_high_level_render.h"
15
16
17/*
18 *
19 * Common
20 *
21 */
22
23void
24chl_frame_state_init(struct chl_frame_state *frame_state,
25 struct render_resources *rr,
26 uint32_t view_count,
27 bool do_timewarp,
28 bool fast_path,
29 struct chl_scratch *scratch)
30{
31 assert(rr != NULL);
32 assert(rr->vk != NULL);
33 assert(view_count <= rr->view_count);
34
35 U_ZERO(frame_state);
36 frame_state->view_count = view_count;
37 frame_state->scratch = scratch;
38
39 comp_render_initial_init( //
40 &frame_state->data, // data
41 fast_path, // fast_path
42 do_timewarp); // do_timewarp
43
44 chl_scratch_state_init_and_get(&frame_state->scratch_state, scratch);
45}
46
47void
48chl_frame_state_fini(struct chl_frame_state *frame_state)
49{
50 if (frame_state->scratch == NULL) {
51 return;
52 }
53
54 chl_scratch_state_discard_or_done(&frame_state->scratch_state, frame_state->scratch);
55
56 U_ZERO(frame_state);
57}
58
59
60/*
61 *
62 * Graphics
63 *
64 */
65
66void
67chl_frame_state_gfx_set_views(struct chl_frame_state *frame_state,
68 const struct xrt_pose world_poses[XRT_MAX_VIEWS],
69 const struct xrt_pose eye_poses[XRT_MAX_VIEWS],
70 const struct xrt_fov fovs[XRT_MAX_VIEWS],
71 uint32_t layer_count)
72{
73 for (uint32_t i = 0; i < frame_state->view_count; i++) {
74 // Which image of the scratch images for this view are we using.
75 uint32_t scratch_index = frame_state->scratch_state.views[i].index;
76
77 // The set of scratch images we are using for this view.
78 struct comp_scratch_single_images *scratch_view = &frame_state->scratch->views[i].cssi;
79
80 // The render target resources for the scratch images.
81 struct render_gfx_target_resources *rsci_rtr = &frame_state->scratch->views[i].targets[scratch_index];
82
83 // Scratch color image.
84 struct render_scratch_color_image *rsci = &scratch_view->images[scratch_index];
85
86 // Use the whole scratch image.
87 struct render_viewport_data layer_viewport_data = {
88 .x = 0,
89 .y = 0,
90 .w = scratch_view->info.width,
91 .h = scratch_view->info.height,
92 };
93
94 comp_render_gfx_add_squash_view( //
95 &frame_state->data, //
96 &world_poses[i], //
97 &eye_poses[i], //
98 &fovs[i], //
99 rsci->image, // squash_image
100 rsci_rtr, // squash_rtr
101 &layer_viewport_data); // squash_viewport_data
102
103 if (layer_count == 0) {
104 frame_state->scratch_state.views[i].used = false;
105 } else {
106 frame_state->scratch_state.views[i].used = !frame_state->data.fast_path;
107 }
108 }
109}
110
111void
112chl_frame_state_gfx_set_target(struct chl_frame_state *frame_state,
113 struct render_gfx_target_resources *target_rtr,
114 const struct render_viewport_data target_viewport_datas[XRT_MAX_VIEWS],
115 const struct xrt_matrix_2x2 vertex_rots[XRT_MAX_VIEWS])
116{
117 // Add the target info.
118 comp_render_gfx_add_target(&frame_state->data, target_rtr);
119
120 for (uint32_t i = 0; i < frame_state->view_count; i++) {
121 // Which image of the scratch images for this view are we using.
122 uint32_t scratch_index = frame_state->scratch_state.views[i].index;
123
124 // The set of scratch images we are using for this view.
125 struct comp_scratch_single_images *scratch_view = &frame_state->scratch->views[i].cssi;
126
127 // Scratch image covers the whole image.
128 struct xrt_normalized_rect layer_norm_rect = {.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f};
129
130 VkImageView sample_view = comp_scratch_single_images_get_sample_view(scratch_view, scratch_index);
131
132 comp_render_gfx_add_target_view( //
133 &frame_state->data, //
134 sample_view, // squash_as_src_sample_view
135 &layer_norm_rect, // squash_as_src_norm_rect
136 &vertex_rots[i], // target_vertex_rot
137 &target_viewport_datas[i]); // target_viewport_data
138 }
139}
140
141
142/*
143 *
144 * Compute
145 *
146 */
147
148void
149chl_frame_state_cs_set_views(struct chl_frame_state *frame_state,
150 const struct xrt_pose world_poses_scanout_begin[XRT_MAX_VIEWS],
151 const struct xrt_pose world_poses_scanout_end[XRT_MAX_VIEWS],
152 const struct xrt_pose eye_poses[XRT_MAX_VIEWS],
153 const struct xrt_fov fovs[XRT_MAX_VIEWS],
154 uint32_t layer_count)
155{
156 for (uint32_t i = 0; i < frame_state->view_count; i++) {
157 // Which image of the scratch images for this view are we using.
158 uint32_t scratch_index = frame_state->scratch_state.views[i].index;
159
160 // The set of scratch images we are using for this view.
161 struct comp_scratch_single_images *scratch_view = &frame_state->scratch->views[i].cssi;
162
163 // Scratch color image.
164 struct render_scratch_color_image *rsci = &scratch_view->images[scratch_index];
165
166 // Use the whole scratch image.
167 struct render_viewport_data layer_viewport_data = {
168 .x = 0,
169 .y = 0,
170 .w = scratch_view->info.width,
171 .h = scratch_view->info.height,
172 };
173
174 VkImageView storage_view = comp_scratch_single_images_get_storage_view(scratch_view, scratch_index);
175
176 comp_render_cs_add_squash_view( //
177 &frame_state->data, //
178 &world_poses_scanout_begin[i], //
179 &world_poses_scanout_end[i], //
180 &eye_poses[i], //
181 &fovs[i], //
182 rsci->image, // squash_image
183 storage_view, // squash_storage_view
184 &layer_viewport_data); // squash_viewport_data
185
186 if (layer_count == 0) {
187 frame_state->scratch_state.views[i].used = false;
188 } else {
189 frame_state->scratch_state.views[i].used = !frame_state->data.fast_path;
190 }
191 }
192}
193
194void
195chl_frame_state_cs_set_target(struct chl_frame_state *frame_state,
196 VkImage target_image,
197 VkImageView target_storage_view,
198 const struct render_viewport_data views[XRT_MAX_VIEWS])
199{
200 // Add the target info.
201 comp_render_cs_add_target( //
202 &frame_state->data, // data
203 target_image, // target_image
204 target_storage_view); // target_unorm_view
205
206 for (uint32_t i = 0; i < frame_state->view_count; i++) {
207 // Which image of the scratch images for this view are we using.
208 uint32_t scratch_index = frame_state->scratch_state.views[i].index;
209
210 // The set of scratch images we are using for this view.
211 struct comp_scratch_single_images *scratch_view = &frame_state->scratch->views[i].cssi;
212
213 // Scratch image covers the whole image.
214 struct xrt_normalized_rect layer_norm_rect = {.x = 0.0f, .y = 0.0f, .w = 1.0f, .h = 1.0f};
215
216 VkImageView sample_view = comp_scratch_single_images_get_sample_view(scratch_view, scratch_index);
217
218 comp_render_cs_add_target_view( //
219 &frame_state->data, //
220 sample_view, // squash_as_src_sample_view
221 &layer_norm_rect, // squash_as_src_norm_rect
222 &views[i]); // target_viewport_data
223 }
224}