···3030DEBUG_GET_ONCE_BOOL_OPTION(compute, "XRT_COMPOSITOR_COMPUTE", false)
3131// clang-format on
32323333+static inline void
3434+add_format(struct comp_settings *s, VkFormat format)
3535+{
3636+ uint32_t count = s->format_count;
3737+3838+ // Just in case, but should never happen.
3939+ if (count >= ARRAY_SIZE(s->formats)) {
4040+ U_LOG_E("Too many formats!");
4141+ return;
4242+ }
4343+4444+ s->formats[count++] = format;
4545+ s->format_count = count;
4646+}
4747+4848+4949+/*
5050+ *
5151+ * 'Exported' functions.
5252+ *
5353+ */
5454+3355void
3456comp_settings_init(struct comp_settings *s, struct xrt_device *xdev)
3557{
···4365 s->use_compute = debug_get_bool_option_compute();
44664567 if (s->use_compute) {
4646- s->color_format = VK_FORMAT_B8G8R8A8_UNORM;
6868+ // This was the default before, keep it first.
6969+ add_format(s, VK_FORMAT_B8G8R8A8_UNORM);
7070+7171+ // This is according to GPU info more supported.
7272+ add_format(s, VK_FORMAT_B8G8R8A8_UNORM);
7373+7474+ // Seen on some NVIDIA cards.
7575+ add_format(s, VK_FORMAT_A8B8G8R8_UNORM_PACK32);
7676+7777+ // Untested: 30 bit format, should we move this higher up?
7878+ add_format(s, VK_FORMAT_A2B10G10R10_UNORM_PACK32);
7979+8080+ // Untested: Super constrained platforms.
8181+ add_format(s, VK_FORMAT_A1R5G5B5_UNORM_PACK16);
4782 } else {
4883#if defined(XRT_OS_ANDROID)
4984 /*
5085 * On Android the most ubiquitous sRGB format is R8G8B8A8_SRGB.
5186 * https://vulkan.gpuinfo.org/listsurfaceformats.php?platform=android
5287 */
5353- s->color_format = VK_FORMAT_R8G8B8A8_SRGB;
8888+ add_format(s, VK_FORMAT_R8G8B8A8_SRGB);
8989+9090+ // Fallback
9191+ add_format(s, VK_FORMAT_B8G8R8A8_SRGB);
5492#elif defined(XRT_OS_LINUX) || defined(XRT_OS_WINDOWS)
5593 /*
5694 * On Linux the most ubiquitous sRGB format is B8G8R8A8_SRGB.
···5997 * On Windows the most ubiquitous sRGB format is B8G8R8A8_SRGB.
6098 * https://vulkan.gpuinfo.org/listsurfaceformats.php?platform=windows
6199 */
6262- s->color_format = VK_FORMAT_B8G8R8A8_SRGB;
100100+ add_format(s, VK_FORMAT_B8G8R8A8_SRGB);
101101+102102+ // Fallback
103103+ add_format(s, VK_FORMAT_R8G8B8A8_SRGB);
63104#else
64105#error "Need to pick default swapchain format for this platform!"
65106#endif
107107+108108+ // Seen as the only sRGB format on some NVIDIA cards.
109109+ add_format(s, VK_FORMAT_A8B8G8R8_SRGB_PACK32);
66110 }
6711168112 s->display = debug_get_num_option_xcb_display();
···7575 //! Image usage for the images, must be followed.
7676 VkImageUsageFlags image_usage;
77777878- //! Preferred format for the images, can be ignored by the target.
7979- VkFormat format;
7878+ //! Acceptable formats for the images, must be followed.
7979+ VkFormat formats[XRT_MAX_SWAPCHAIN_FORMATS];
8080+8181+ // Number of formats.
8282+ uint32_t format_count;
80838184 //! Preferred extent, can be ignored by the target.
8285 VkExtent2D extent;
+68-94
src/xrt/compositor/main/comp_target_swapchain.c
···26262727/*
2828 *
2929- * Types, defines and data.
3030- *
3131- */
3232-3333-/*!
3434- * These formats will be 'preferred' - we may wish to give preference
3535- * to higher bit depths if they are available, but most display devices we are
3636- * interested in should support one these.
3737- */
3838-static VkFormat preferred_color_formats[] = {
3939- VK_FORMAT_B8G8R8A8_SRGB, //
4040- VK_FORMAT_R8G8B8A8_SRGB, //
4141- VK_FORMAT_B8G8R8A8_UNORM, //
4242- VK_FORMAT_R8G8B8A8_UNORM, //
4343- VK_FORMAT_A8B8G8R8_UNORM_PACK32, // Just in case.
4444-};
4545-4646-4747-/*
4848- *
4929 * Vulkan functions.
5030 *
5131 */
···230210}
231211232212static bool
233233-find_surface_format(struct comp_target_swapchain *cts, const struct vk_surface_info *info, VkSurfaceFormatKHR *format)
213213+pick_first_matching_surface_format(const struct comp_target_create_images_info *create_info,
214214+ VkSurfaceFormatKHR *surface_formats,
215215+ uint32_t surface_format_count,
216216+ VkSurfaceFormatKHR *out_surface_format)
234217{
235235- VkSurfaceFormatKHR *formats_for_colorspace = NULL;
236236- formats_for_colorspace = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, info->format_count);
218218+ for (uint32_t i = 0; i < create_info->format_count; i++) {
219219+ // Format to check against.
220220+ VkFormat format = create_info->formats[i];
221221+222222+ for (uint32_t k = 0; k < surface_format_count; k++) {
223223+ if (surface_formats[k].format == format) {
224224+ // Perfect match.
225225+ *out_surface_format = surface_formats[i];
226226+ return true;
227227+ }
228228+ }
229229+ }
237230238238- uint32_t format_for_colorspace_count = 0;
239239- uint32_t pref_format_count = ARRAY_SIZE(preferred_color_formats);
231231+ return false;
232232+}
240233241241- // Gather formats that match our color space, we will select
242242- // from these in preference to others.
234234+static bool
235235+find_surface_format(struct comp_target_swapchain *cts,
236236+ const struct comp_target_create_images_info *create_info,
237237+ const struct vk_surface_info *info,
238238+ VkSurfaceFormatKHR *out_surface_format)
239239+{
240240+ VkSurfaceFormatKHR *colorspace_matches = NULL;
241241+ uint32_t colorspace_match_count = 0;
242242+ bool bret = false;
243243244244245245+ /*
246246+ * Gather surface formats that match our color space,
247247+ * we will select from these in preference to others.
248248+ */
249249+ colorspace_matches = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, info->format_count);
245250 for (uint32_t i = 0; i < info->format_count; i++) {
246251 if (info->formats[i].colorSpace == cts->preferred.color_space) {
247247- formats_for_colorspace[format_for_colorspace_count] = info->formats[i];
248248- format_for_colorspace_count++;
252252+ colorspace_matches[colorspace_match_count++] = info->formats[i];
249253 }
250254 }
251255252252- if (format_for_colorspace_count > 0) {
253253- // we have at least one format with our preferred colorspace
254254- // if we have one that is on our preferred formats list, use it
256256+ /*
257257+ * We first try the list of surface formats with
258258+ * a matching color space, if any, to the one we want.
259259+ */
260260+ bret = pick_first_matching_surface_format( //
261261+ create_info, //
262262+ colorspace_matches, //
263263+ colorspace_match_count, //
264264+ out_surface_format); //
255265256256- for (uint32_t i = 0; i < format_for_colorspace_count; i++) {
257257- if (formats_for_colorspace[i].format == cts->preferred.color_format) {
258258- // perfect match.
259259- *format = formats_for_colorspace[i];
260260- goto cleanup;
261261- }
262262- }
266266+ // Always free these formats.
267267+ free(colorspace_matches);
263268264264- // we don't have our swapchain default format and colorspace,
265265- // but we may have at least one preferred format with the
266266- // correct colorspace.
267267- for (uint32_t i = 0; i < format_for_colorspace_count; i++) {
268268- for (uint32_t j = 0; j < pref_format_count; j++) {
269269- if (formats_for_colorspace[i].format == preferred_color_formats[j]) {
270270- *format = formats_for_colorspace[i];
271271- goto cleanup;
272272- }
273273- }
274274- }
269269+ // Check result.
270270+ if (bret) {
271271+ // Done now.
272272+ goto done;
273273+ }
275274276276- // are we still here? this means we have a format with our
277277- // preferred colorspace but we have no preferred color format -
278278- // maybe we only have 10/12 bpc or 15/16bpp format. return the
279279- // first one we have, at least its in the right color space.
280280- *format = formats_for_colorspace[0];
281281- COMP_ERROR(cts->base.c, "Returning unknown color format");
282282- goto cleanup;
283283-284284- } else {
285285-286286- // we have nothing with the preferred colorspace? we can try to
287287- // return a preferred format at least
288288- for (uint32_t i = 0; i < info->format_count; i++) {
289289- for (uint32_t j = 0; j < pref_format_count; j++) {
290290- if (info->formats[i].format == preferred_color_formats[j]) {
291291- *format = formats_for_colorspace[i];
292292- COMP_ERROR(cts->base.c,
293293- "Returning known-wrong color space! Color shift may occur.");
294294- goto cleanup;
295295- }
296296- }
297297- }
298298- // if we are still here, we should just return the first format
299299- // we have. we know its the wrong colorspace, and its not on our
300300- // list of preferred formats, but its something.
301301- *format = info->formats[0];
302302- COMP_ERROR(cts->base.c,
303303- "Returning fallback format! cue up some Kenny Loggins, cos we're in the DANGER ZONE!");
304304- goto cleanup;
275275+ /*
276276+ * Try to find any surface format that at least has a matching
277277+ * Vulkan format to one of the formats the compositor can use.
278278+ */
279279+ bret = pick_first_matching_surface_format( //
280280+ create_info, //
281281+ info->formats, //
282282+ info->format_count, //
283283+ out_surface_format); //
284284+ if (!bret) {
285285+ COMP_ERROR(cts->base.c, "Could not find any matching surface formats!");
286286+ return false;
305287 }
306288307307- COMP_ERROR(cts->base.c, "We should not be here");
308308- goto error;
289289+ COMP_WARN(cts->base.c, "Returning known-wrong color space! Color shift may occur.");
309290310310-cleanup:
311311- free(formats_for_colorspace);
312312-291291+done:
313292 COMP_DEBUG(cts->base.c,
314293 "VkSurfaceFormatKHR"
315294 "\n\tpicked: [format = %s, colorSpace = %s]"
316295 "\n\tpreferred: [format = %s, colorSpace = %s]",
317317- vk_format_string(format->format), //
318318- vk_color_space_string(format->colorSpace), //
319319- vk_format_string(cts->preferred.color_format), //
320320- vk_color_space_string(cts->preferred.color_space)); //
296296+ vk_format_string(out_surface_format->format), //
297297+ vk_color_space_string(out_surface_format->colorSpace), //
298298+ vk_format_string(create_info->formats[0]), //
299299+ vk_color_space_string(cts->preferred.color_space)); //
321300322301 return true;
323323-324324-error:
325325- free(formats_for_colorspace);
326326- return false;
327302}
328303329304static void
···665640 cts->base.image_count = 0;
666641 cts->swapchain.handle = VK_NULL_HANDLE;
667642 cts->present_mode = create_info->present_mode;
668668- cts->preferred.color_format = create_info->format;
669643 cts->preferred.color_space = create_info->color_space;
670644671645···702676 }
703677704678 // Find the correct format.
705705- if (!find_surface_format(cts, &info, &cts->surface.format)) {
679679+ if (!find_surface_format(cts, create_info, &info, &cts->surface.format)) {
706680 goto error_print_and_free;
707681 }
708682