···268{
269 struct xrt_system_compositor_info *sys_info = &c->sys_info;
270271+ /*
272+ * Required by OpenXR spec (minimum 16).
273+ *
274+ * NOTE: When using Vulkan compositor components (c/render, c/util),
275+ * call render_max_layers_capable() to clamp this value based on
276+ * actual device limits.
277+ */
278 sys_info->max_layers = XRT_MAX_LAYERS;
279280 uint32_t view_count = xdev->hmd->view_count;
+18
src/xrt/compositor/render/render_interface.h
···93//! The binding that the shared layer fragment shader has its source on.
94#define RENDER_BINDING_LAYER_SHARED_SRC 1
95000009697/*
98 *
99 * Util functions.
100 *
101 */
0000000000000102103/*!
104 * Create a simplified projection matrix for timewarp.
···93//! The binding that the shared layer fragment shader has its source on.
94#define RENDER_BINDING_LAYER_SHARED_SRC 1
9596+/*!
97+ * The maximum number samplers per view that can be used by the compute shader
98+ * for layer composition (layer.comp)
99+ */
100+#define RENDER_CS_MAX_SAMPLERS_PER_VIEW 2
101102/*
103 *
104 * Util functions.
105 *
106 */
107+108+/*!
109+ * Determines the maximum number of compositor layers supported based on Vulkan
110+ * device limits and the composition path being used.
111+ *
112+ * @param vk Vulkan bundle containing device properties
113+ * @param use_compute True if using compute pipeline path, false for graphics
114+ * @param desired_max_layers Maximum layers requested by the compositor
115+ * @return Actual maximum layers supported, clamped by device limits (minimum 16)
116+ *
117+ */
118+uint32_t
119+render_max_layers_capable(const struct vk_bundle *vk, bool use_compute, uint32_t desired_max_layers);
120121/*!
122 * Create a simplified projection matrix for timewarp.
···87 *
88 */
8990+uint32_t
91+render_max_layers_capable(const struct vk_bundle *vk, bool use_compute, uint32_t desired_max_layers)
92+{
93+ /*!
94+ * Graphics pipeline:
95+ *
96+ * This path has no relevant Vulkan device limits that would
97+ * constrain the maximum number of layers (each layer uses a single descriptor
98+ * set bound individually per draw).
99+ */
100+ if (!use_compute) {
101+ // The min required by OpenXR spec is 16.
102+ return MAX(desired_max_layers, 16);
103+ }
104+105+ /*!
106+ * Compute pipeline:
107+ *
108+ * Clamp max layers based on compute pipeline descriptor limits.
109+ *
110+ * The compute path uses an array of combined image samplers, with
111+ * @ref samplers_per_layer samplers needed per layer. We check both the
112+ * per-stage sampler and sampled image limits, then calculate the
113+ * maximum number of complete layers that fit within those limits.
114+ */
115+ uint32_t desired_image_sampler_count = desired_max_layers * RENDER_CS_MAX_SAMPLERS_PER_VIEW;
116+117+ const uint32_t max_sizes[] = {
118+ vk->limits.max_per_stage_descriptor_samplers,
119+ vk->limits.max_per_stage_descriptor_sampled_images,
120+ };
121+ for (uint32_t i = 0; i < ARRAY_SIZE(max_sizes); ++i) {
122+ desired_image_sampler_count = MIN(desired_image_sampler_count, max_sizes[i]);
123+ }
124+125+ const uint32_t calculated_max_layers = desired_image_sampler_count / RENDER_CS_MAX_SAMPLERS_PER_VIEW;
126+127+ if (calculated_max_layers < 16) {
128+ VK_WARN(vk,
129+ "Device supports only %u compositor layers due to Vulkan limits. "
130+ "which is below Vulkan minimum of 16. "
131+ "This may indicate a driver bug. Attempting 16 anyway.",
132+ calculated_max_layers);
133+ }
134+135+ // The min required by OpenXR spec is 16.
136+ return MAX(calculated_max_layers, 16);
137+}
138+139void
140render_calc_time_warp_matrix(const struct xrt_pose *src_pose,
141 const struct xrt_fov *src_fov,
+7-1
src/xrt/targets/sdl_test/sdl_compositor.c
···256{
257 struct xrt_system_compositor_info *sys_info = &c->sys_info;
258259- // Required by OpenXR spec.
000000260 sys_info->max_layers = XRT_MAX_LAYERS;
261262 // UUIDs and LUID already set in vk init.
···256{
257 struct xrt_system_compositor_info *sys_info = &c->sys_info;
258259+ /*
260+ * Required by OpenXR spec (minimum 16).
261+ *
262+ * NOTE: When using Vulkan compositor components (c/render, c/util),
263+ * call render_max_layers_capable() to clamp this value based on
264+ * actual device limits.
265+ */
266 sys_info->max_layers = XRT_MAX_LAYERS;
267268 // UUIDs and LUID already set in vk init.