The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

c/main: Refactor how surface formats are handled

authored by

Jakob Bornecrantz and committed by
Simon Zeni
57e93738 a6e9893f

+133 -102
+5 -1
src/xrt/compositor/main/comp_renderer.c
··· 535 535 .width = r->c->settings.preferred.width, 536 536 .height = r->c->settings.preferred.height, 537 537 }, 538 - .format = r->settings->color_format, 539 538 .image_usage = image_usage, 540 539 .color_space = r->settings->color_space, 541 540 .present_mode = r->settings->present_mode, 542 541 }; 542 + 543 + static_assert(ARRAY_SIZE(info.formats) == ARRAY_SIZE(r->c->settings.formats), "Miss-match format array sizes"); 544 + for (uint32_t i = 0; i < r->c->settings.format_count; i++) { 545 + info.formats[info.format_count++] = r->c->settings.formats[i]; 546 + } 543 547 544 548 comp_target_create_images(r->c->target, &info); 545 549
+47 -3
src/xrt/compositor/main/comp_settings.c
··· 30 30 DEBUG_GET_ONCE_BOOL_OPTION(compute, "XRT_COMPOSITOR_COMPUTE", false) 31 31 // clang-format on 32 32 33 + static inline void 34 + add_format(struct comp_settings *s, VkFormat format) 35 + { 36 + uint32_t count = s->format_count; 37 + 38 + // Just in case, but should never happen. 39 + if (count >= ARRAY_SIZE(s->formats)) { 40 + U_LOG_E("Too many formats!"); 41 + return; 42 + } 43 + 44 + s->formats[count++] = format; 45 + s->format_count = count; 46 + } 47 + 48 + 49 + /* 50 + * 51 + * 'Exported' functions. 52 + * 53 + */ 54 + 33 55 void 34 56 comp_settings_init(struct comp_settings *s, struct xrt_device *xdev) 35 57 { ··· 43 65 s->use_compute = debug_get_bool_option_compute(); 44 66 45 67 if (s->use_compute) { 46 - s->color_format = VK_FORMAT_B8G8R8A8_UNORM; 68 + // This was the default before, keep it first. 69 + add_format(s, VK_FORMAT_B8G8R8A8_UNORM); 70 + 71 + // This is according to GPU info more supported. 72 + add_format(s, VK_FORMAT_B8G8R8A8_UNORM); 73 + 74 + // Seen on some NVIDIA cards. 75 + add_format(s, VK_FORMAT_A8B8G8R8_UNORM_PACK32); 76 + 77 + // Untested: 30 bit format, should we move this higher up? 78 + add_format(s, VK_FORMAT_A2B10G10R10_UNORM_PACK32); 79 + 80 + // Untested: Super constrained platforms. 81 + add_format(s, VK_FORMAT_A1R5G5B5_UNORM_PACK16); 47 82 } else { 48 83 #if defined(XRT_OS_ANDROID) 49 84 /* 50 85 * On Android the most ubiquitous sRGB format is R8G8B8A8_SRGB. 51 86 * https://vulkan.gpuinfo.org/listsurfaceformats.php?platform=android 52 87 */ 53 - s->color_format = VK_FORMAT_R8G8B8A8_SRGB; 88 + add_format(s, VK_FORMAT_R8G8B8A8_SRGB); 89 + 90 + // Fallback 91 + add_format(s, VK_FORMAT_B8G8R8A8_SRGB); 54 92 #elif defined(XRT_OS_LINUX) || defined(XRT_OS_WINDOWS) 55 93 /* 56 94 * On Linux the most ubiquitous sRGB format is B8G8R8A8_SRGB. ··· 59 97 * On Windows the most ubiquitous sRGB format is B8G8R8A8_SRGB. 60 98 * https://vulkan.gpuinfo.org/listsurfaceformats.php?platform=windows 61 99 */ 62 - s->color_format = VK_FORMAT_B8G8R8A8_SRGB; 100 + add_format(s, VK_FORMAT_B8G8R8A8_SRGB); 101 + 102 + // Fallback 103 + add_format(s, VK_FORMAT_R8G8B8A8_SRGB); 63 104 #else 64 105 #error "Need to pick default swapchain format for this platform!" 65 106 #endif 107 + 108 + // Seen as the only sRGB format on some NVIDIA cards. 109 + add_format(s, VK_FORMAT_A8B8G8R8_SRGB_PACK32); 66 110 } 67 111 68 112 s->display = debug_get_num_option_xcb_display();
+3 -1
src/xrt/compositor/main/comp_settings.h
··· 50 50 51 51 bool use_compute; 52 52 53 - VkFormat color_format; 53 + VkFormat formats[XRT_MAX_SWAPCHAIN_FORMATS]; 54 + uint32_t format_count; 55 + 54 56 VkColorSpaceKHR color_space; 55 57 VkPresentModeKHR present_mode; 56 58
+5 -2
src/xrt/compositor/main/comp_target.h
··· 75 75 //! Image usage for the images, must be followed. 76 76 VkImageUsageFlags image_usage; 77 77 78 - //! Preferred format for the images, can be ignored by the target. 79 - VkFormat format; 78 + //! Acceptable formats for the images, must be followed. 79 + VkFormat formats[XRT_MAX_SWAPCHAIN_FORMATS]; 80 + 81 + // Number of formats. 82 + uint32_t format_count; 80 83 81 84 //! Preferred extent, can be ignored by the target. 82 85 VkExtent2D extent;
+68 -94
src/xrt/compositor/main/comp_target_swapchain.c
··· 26 26 27 27 /* 28 28 * 29 - * Types, defines and data. 30 - * 31 - */ 32 - 33 - /*! 34 - * These formats will be 'preferred' - we may wish to give preference 35 - * to higher bit depths if they are available, but most display devices we are 36 - * interested in should support one these. 37 - */ 38 - static VkFormat preferred_color_formats[] = { 39 - VK_FORMAT_B8G8R8A8_SRGB, // 40 - VK_FORMAT_R8G8B8A8_SRGB, // 41 - VK_FORMAT_B8G8R8A8_UNORM, // 42 - VK_FORMAT_R8G8B8A8_UNORM, // 43 - VK_FORMAT_A8B8G8R8_UNORM_PACK32, // Just in case. 44 - }; 45 - 46 - 47 - /* 48 - * 49 29 * Vulkan functions. 50 30 * 51 31 */ ··· 230 210 } 231 211 232 212 static bool 233 - find_surface_format(struct comp_target_swapchain *cts, const struct vk_surface_info *info, VkSurfaceFormatKHR *format) 213 + pick_first_matching_surface_format(const struct comp_target_create_images_info *create_info, 214 + VkSurfaceFormatKHR *surface_formats, 215 + uint32_t surface_format_count, 216 + VkSurfaceFormatKHR *out_surface_format) 234 217 { 235 - VkSurfaceFormatKHR *formats_for_colorspace = NULL; 236 - formats_for_colorspace = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, info->format_count); 218 + for (uint32_t i = 0; i < create_info->format_count; i++) { 219 + // Format to check against. 220 + VkFormat format = create_info->formats[i]; 221 + 222 + for (uint32_t k = 0; k < surface_format_count; k++) { 223 + if (surface_formats[k].format == format) { 224 + // Perfect match. 225 + *out_surface_format = surface_formats[i]; 226 + return true; 227 + } 228 + } 229 + } 237 230 238 - uint32_t format_for_colorspace_count = 0; 239 - uint32_t pref_format_count = ARRAY_SIZE(preferred_color_formats); 231 + return false; 232 + } 240 233 241 - // Gather formats that match our color space, we will select 242 - // from these in preference to others. 234 + static bool 235 + find_surface_format(struct comp_target_swapchain *cts, 236 + const struct comp_target_create_images_info *create_info, 237 + const struct vk_surface_info *info, 238 + VkSurfaceFormatKHR *out_surface_format) 239 + { 240 + VkSurfaceFormatKHR *colorspace_matches = NULL; 241 + uint32_t colorspace_match_count = 0; 242 + bool bret = false; 243 243 244 244 245 + /* 246 + * Gather surface formats that match our color space, 247 + * we will select from these in preference to others. 248 + */ 249 + colorspace_matches = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, info->format_count); 245 250 for (uint32_t i = 0; i < info->format_count; i++) { 246 251 if (info->formats[i].colorSpace == cts->preferred.color_space) { 247 - formats_for_colorspace[format_for_colorspace_count] = info->formats[i]; 248 - format_for_colorspace_count++; 252 + colorspace_matches[colorspace_match_count++] = info->formats[i]; 249 253 } 250 254 } 251 255 252 - if (format_for_colorspace_count > 0) { 253 - // we have at least one format with our preferred colorspace 254 - // if we have one that is on our preferred formats list, use it 256 + /* 257 + * We first try the list of surface formats with 258 + * a matching color space, if any, to the one we want. 259 + */ 260 + bret = pick_first_matching_surface_format( // 261 + create_info, // 262 + colorspace_matches, // 263 + colorspace_match_count, // 264 + out_surface_format); // 255 265 256 - for (uint32_t i = 0; i < format_for_colorspace_count; i++) { 257 - if (formats_for_colorspace[i].format == cts->preferred.color_format) { 258 - // perfect match. 259 - *format = formats_for_colorspace[i]; 260 - goto cleanup; 261 - } 262 - } 266 + // Always free these formats. 267 + free(colorspace_matches); 263 268 264 - // we don't have our swapchain default format and colorspace, 265 - // but we may have at least one preferred format with the 266 - // correct colorspace. 267 - for (uint32_t i = 0; i < format_for_colorspace_count; i++) { 268 - for (uint32_t j = 0; j < pref_format_count; j++) { 269 - if (formats_for_colorspace[i].format == preferred_color_formats[j]) { 270 - *format = formats_for_colorspace[i]; 271 - goto cleanup; 272 - } 273 - } 274 - } 269 + // Check result. 270 + if (bret) { 271 + // Done now. 272 + goto done; 273 + } 275 274 276 - // are we still here? this means we have a format with our 277 - // preferred colorspace but we have no preferred color format - 278 - // maybe we only have 10/12 bpc or 15/16bpp format. return the 279 - // first one we have, at least its in the right color space. 280 - *format = formats_for_colorspace[0]; 281 - COMP_ERROR(cts->base.c, "Returning unknown color format"); 282 - goto cleanup; 283 - 284 - } else { 285 - 286 - // we have nothing with the preferred colorspace? we can try to 287 - // return a preferred format at least 288 - for (uint32_t i = 0; i < info->format_count; i++) { 289 - for (uint32_t j = 0; j < pref_format_count; j++) { 290 - if (info->formats[i].format == preferred_color_formats[j]) { 291 - *format = formats_for_colorspace[i]; 292 - COMP_ERROR(cts->base.c, 293 - "Returning known-wrong color space! Color shift may occur."); 294 - goto cleanup; 295 - } 296 - } 297 - } 298 - // if we are still here, we should just return the first format 299 - // we have. we know its the wrong colorspace, and its not on our 300 - // list of preferred formats, but its something. 301 - *format = info->formats[0]; 302 - COMP_ERROR(cts->base.c, 303 - "Returning fallback format! cue up some Kenny Loggins, cos we're in the DANGER ZONE!"); 304 - goto cleanup; 275 + /* 276 + * Try to find any surface format that at least has a matching 277 + * Vulkan format to one of the formats the compositor can use. 278 + */ 279 + bret = pick_first_matching_surface_format( // 280 + create_info, // 281 + info->formats, // 282 + info->format_count, // 283 + out_surface_format); // 284 + if (!bret) { 285 + COMP_ERROR(cts->base.c, "Could not find any matching surface formats!"); 286 + return false; 305 287 } 306 288 307 - COMP_ERROR(cts->base.c, "We should not be here"); 308 - goto error; 289 + COMP_WARN(cts->base.c, "Returning known-wrong color space! Color shift may occur."); 309 290 310 - cleanup: 311 - free(formats_for_colorspace); 312 - 291 + done: 313 292 COMP_DEBUG(cts->base.c, 314 293 "VkSurfaceFormatKHR" 315 294 "\n\tpicked: [format = %s, colorSpace = %s]" 316 295 "\n\tpreferred: [format = %s, colorSpace = %s]", 317 - vk_format_string(format->format), // 318 - vk_color_space_string(format->colorSpace), // 319 - vk_format_string(cts->preferred.color_format), // 320 - vk_color_space_string(cts->preferred.color_space)); // 296 + vk_format_string(out_surface_format->format), // 297 + vk_color_space_string(out_surface_format->colorSpace), // 298 + vk_format_string(create_info->formats[0]), // 299 + vk_color_space_string(cts->preferred.color_space)); // 321 300 322 301 return true; 323 - 324 - error: 325 - free(formats_for_colorspace); 326 - return false; 327 302 } 328 303 329 304 static void ··· 665 640 cts->base.image_count = 0; 666 641 cts->swapchain.handle = VK_NULL_HANDLE; 667 642 cts->present_mode = create_info->present_mode; 668 - cts->preferred.color_format = create_info->format; 669 643 cts->preferred.color_space = create_info->color_space; 670 644 671 645 ··· 702 676 } 703 677 704 678 // Find the correct format. 705 - if (!find_surface_format(cts, &info, &cts->surface.format)) { 679 + if (!find_surface_format(cts, create_info, &info, &cts->surface.format)) { 706 680 goto error_print_and_free; 707 681 } 708 682
+5 -1
src/xrt/compositor/main/comp_window_peek.c
··· 55 55 { 56 56 struct comp_target_create_images_info info = { 57 57 .extent = {w->width, w->height}, 58 - .format = w->c->settings.color_format, 59 58 .color_space = w->c->settings.color_space, 60 59 .image_usage = PEEK_IMAGE_USAGE, 61 60 .present_mode = VK_PRESENT_MODE_MAILBOX_KHR, 62 61 }; 62 + 63 + static_assert(ARRAY_SIZE(info.formats) == ARRAY_SIZE(w->c->settings.formats), "Miss-match format array sizes"); 64 + for (uint32_t i = 0; i < w->c->settings.format_count; i++) { 65 + info.formats[info.format_count++] = w->c->settings.formats[i]; 66 + } 63 67 64 68 comp_target_create_images(&w->base.base, &info); 65 69 }