Просмотр исходного кода

xr: Return all valid swapchain formats in runtime's preference (#16352)

Beyley Cardellio 1 день назад
Родитель
Сommit
65360c9dae
3 измененных файлов с 60 добавлено и 131 удалено
  1. 21 57
      src/gpu/d3d12/SDL_gpu_d3d12.c
  2. 21 70
      src/gpu/vulkan/SDL_gpu_vulkan.c
  3. 18 4
      test/testgpu_spinning_cube_xr.c

+ 21 - 57
src/gpu/d3d12/SDL_gpu_d3d12.c

@@ -601,27 +601,10 @@ static DXGI_FORMAT SDLToD3D12_TypelessFormat[] = {
 SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TypelessFormat, SDL_arraysize(SDLToD3D12_TypelessFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
 
 #ifdef HAVE_GPU_OPENXR
-// For XR sRGB format selection - maps DXGI sRGB formats to SDL formats
-typedef struct TextureFormatPair
-{
-    DXGI_FORMAT dxgi;
-    SDL_GPUTextureFormat sdl;
-} TextureFormatPair;
-
-static TextureFormatPair SDLToD3D12_TextureFormat_SrgbOnly[] = {
-    { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB },
-    { DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB },
-    { DXGI_FORMAT_BC1_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB },
-    { DXGI_FORMAT_BC2_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB },
-    { DXGI_FORMAT_BC3_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB },
-    { DXGI_FORMAT_BC7_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB },
-};
-
 // Forward declarations for XR helper functions
 static bool D3D12_INTERNAL_SearchForOpenXrGpuExtension(XrExtensionProperties *found_extension);
 static XrResult D3D12_INTERNAL_GetXrGraphicsRequirements(XrInstance instance, XrSystemId systemId, D3D_FEATURE_LEVEL *minimumFeatureLevel, LUID *adapter);
 static bool D3D12_INTERNAL_GetAdapterByLuid(LUID luid, IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapter);
-static bool D3D12_INTERNAL_FindXRSrgbSwapchain(int64_t *supportedFormats, Uint32 supportedFormatsCount, SDL_GPUTextureFormat *sdlFormat, DXGI_FORMAT *dxgiFormat);
 #endif /* HAVE_GPU_OPENXR */
 
 static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
@@ -9019,24 +9002,6 @@ static bool D3D12_INTERNAL_GetAdapterByLuid(LUID luid, IDXGIFactory1 *factory, I
         IDXGIAdapter1_Release(adapter);
     }
 }
-
-static bool D3D12_INTERNAL_FindXRSrgbSwapchain(
-    int64_t *supportedFormats,
-    Uint32 supportedFormatsCount,
-    SDL_GPUTextureFormat *sdlFormat,
-    DXGI_FORMAT *dxgiFormat)
-{
-    for (Uint32 i = 0; i < SDL_arraysize(SDLToD3D12_TextureFormat_SrgbOnly); i++) {
-        for (Uint32 j = 0; j < supportedFormatsCount; j++) {
-            if (SDLToD3D12_TextureFormat_SrgbOnly[i].dxgi == supportedFormats[j]) {
-                *sdlFormat = SDLToD3D12_TextureFormat_SrgbOnly[i].sdl;
-                *dxgiFormat = SDLToD3D12_TextureFormat_SrgbOnly[i].dxgi;
-                return true;
-            }
-        }
-    }
-    return false;
-}
 #endif /* HAVE_GPU_OPENXR */
 
 static XrResult D3D12_DestroyXRSwapchain(
@@ -9106,38 +9071,37 @@ static SDL_GPUTextureFormat* D3D12_GetXRSwapchainFormats(
         return NULL;
     }
 
-    // FIXME: For now we're just searching for the optimal format, not all supported formats.
-    // FIXME: Expand this search for all SDL_GPU formats!
-
-    SDL_GPUTextureFormat sdlFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
-    DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
-    // The OpenXR spec recommends applications not submit linear data, so let's try to explicitly find an sRGB swapchain before we search the whole list
-    if (!D3D12_INTERNAL_FindXRSrgbSwapchain(supported_formats, num_supported_formats, &sdlFormat, &dxgiFormat)) {
-        // Iterate over all formats the runtime supports
-        for (i = 0; i < num_supported_formats && dxgiFormat == DXGI_FORMAT_UNKNOWN; i++) {
-            // Iterate over all formats we support
-            for (j = 0; j < SDL_arraysize(SDLToD3D12_TextureFormat); j++) {
-                // Pick the first format the runtime wants that we also support, the runtime should return these in order of preference
-                if (SDLToD3D12_TextureFormat[j] == supported_formats[i]) {
-                    dxgiFormat = (DXGI_FORMAT)supported_formats[i];
-                    sdlFormat = j;
-                    break;
-                }
+    SDL_GPUTextureFormat *sdl_formats = SDL_stack_alloc(SDL_GPUTextureFormat, num_supported_formats);
+    uint32_t num_found_formats = 0;
+
+    // Iterate over all formats the runtime supports
+    for (i = 0; i < num_supported_formats; i++) {
+        // Iterate over all formats we support
+        for (j = 0; j < SDL_arraysize(SDLToD3D12_TextureFormat); j++) {
+            if (SDLToD3D12_TextureFormat[j] == supported_formats[i]) {
+                // Add the format match we found, linearly. The output order should match the order of the runtime.
+                sdl_formats[num_found_formats++] = j;
+                break;
             }
         }
     }
 
     SDL_stack_free(supported_formats);
 
-    if (dxgiFormat == DXGI_FORMAT_UNKNOWN) {
+    if (num_found_formats == 0) {
         SDL_SetError("Failed to find a swapchain format supported by both OpenXR and SDL");
+        SDL_stack_free(sdl_formats);
         return NULL;
     }
 
-    SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat*) SDL_malloc(sizeof(SDL_GPUTextureFormat) * 2);
-    retval[0] = sdlFormat;
-    retval[1] = SDL_GPU_TEXTUREFORMAT_INVALID;
-    *num_formats = 1;
+    SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat *)SDL_calloc((size_t)num_found_formats + 1, sizeof(SDL_GPUTextureFormat));
+    SDL_memcpy(retval, sdl_formats, sizeof(SDL_GPUTextureFormat) * num_found_formats); // Copy the translated formats
+    retval[num_found_formats] = SDL_GPU_TEXTUREFORMAT_INVALID; // Add a termination for good measure
+
+    *num_formats = num_found_formats;
+
+    SDL_stack_free(supported_formats);
+
     return retval;
 #else
     SDL_SetError("SDL not built with OpenXR support");

+ 21 - 70
src/gpu/vulkan/SDL_gpu_vulkan.c

@@ -95,37 +95,6 @@ static VkPresentModeKHR SDLToVK_PresentMode[] = {
     VK_PRESENT_MODE_MAILBOX_KHR
 };
 
-// NOTE: this is behind an ifdef guard because without, it would trigger an "unused variable" error when OpenXR support is disabled
-#ifdef HAVE_GPU_OPENXR
-typedef struct TextureFormatPair {
-    VkFormat vk;
-    SDL_GPUTextureFormat sdl;
-} TextureFormatPair;
-
-static TextureFormatPair SDLToVK_TextureFormat_SrgbOnly[] = {
-    {VK_FORMAT_R8G8B8A8_SRGB, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB},
-    {VK_FORMAT_B8G8R8A8_SRGB, SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB},
-    {VK_FORMAT_BC1_RGBA_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB},
-    {VK_FORMAT_BC2_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB},
-    {VK_FORMAT_BC3_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB},
-    {VK_FORMAT_BC7_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB},
-    {VK_FORMAT_ASTC_4x4_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB},
-    {VK_FORMAT_ASTC_5x4_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB},
-    {VK_FORMAT_ASTC_5x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB},
-    {VK_FORMAT_ASTC_6x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB},
-    {VK_FORMAT_ASTC_6x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB},
-    {VK_FORMAT_ASTC_8x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB},
-    {VK_FORMAT_ASTC_8x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB},
-    {VK_FORMAT_ASTC_8x8_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB},
-    {VK_FORMAT_ASTC_10x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB},
-    {VK_FORMAT_ASTC_10x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB},
-    {VK_FORMAT_ASTC_10x8_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB},
-    {VK_FORMAT_ASTC_10x10_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB},
-    {VK_FORMAT_ASTC_12x10_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB},
-    {VK_FORMAT_ASTC_12x12_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB},
-};
-#endif // HAVE_GPU_OPENXR
-
 static VkFormat SDLToVK_TextureFormat[] = {
     VK_FORMAT_UNDEFINED,                   // INVALID
     VK_FORMAT_R8_UNORM,                    // A8_UNORM
@@ -13126,23 +13095,6 @@ static XrResult VULKAN_DestroyXRSwapchain(
 #endif
 }
 
-#ifdef HAVE_GPU_OPENXR
-static bool VULKAN_INTERNAL_FindXRSrgbSwapchain(int64_t *supportedFormats, Uint32 numFormats, SDL_GPUTextureFormat *sdlFormat, int64_t *vkFormat)
-{
-    for (Uint32 i = 0; i < SDL_arraysize(SDLToVK_TextureFormat_SrgbOnly); i++) {
-        for (Uint32 j = 0; j < numFormats; j++) {
-            if (SDLToVK_TextureFormat_SrgbOnly[i].vk == supportedFormats[j]) {
-                *sdlFormat = SDLToVK_TextureFormat_SrgbOnly[i].sdl;
-                *vkFormat = SDLToVK_TextureFormat_SrgbOnly[i].vk;
-                return true;
-            }
-        }
-    }
-
-    return false;
-}
-#endif // HAVE_GPU_OPENXR
-
 static SDL_GPUTextureFormat* VULKAN_GetXRSwapchainFormats(
     SDL_GPURenderer *driverData,
     XrSession session,
@@ -13163,38 +13115,37 @@ static SDL_GPUTextureFormat* VULKAN_GetXRSwapchainFormats(
         return NULL;
     }
 
-    // FIXME: For now we're just searching for the optimal format, not all supported formats.
-    // FIXME: Expand this search for all SDL_GPU formats!
-
-    SDL_GPUTextureFormat sdlFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
-    int64_t vkFormat = VK_FORMAT_UNDEFINED;
-    // The OpenXR spec recommends applications not submit linear data, so let's try to explicitly find an sRGB swapchain before we search the whole list
-    if (!VULKAN_INTERNAL_FindXRSrgbSwapchain(supported_formats, num_supported_formats, &sdlFormat, &vkFormat)) {
-        // Iterate over all formats the runtime supports
-        for (i = 0; i < num_supported_formats && vkFormat == VK_FORMAT_UNDEFINED; i++) {
-            // Iterate over all formats we support
-            for (j = 0; j < SDL_arraysize(SDLToVK_TextureFormat); j++) {
-                // Pick the first format the runtime wants that we also support, the runtime should return these in order of preference
-                if (SDLToVK_TextureFormat[j] == supported_formats[i]) {
-                    vkFormat = supported_formats[i];
-                    sdlFormat = j;
-                    break;
-                }
+    SDL_GPUTextureFormat *sdl_formats = SDL_stack_alloc(SDL_GPUTextureFormat, num_supported_formats);
+    uint32_t num_found_formats = 0;
+
+    // Iterate over all formats the runtime supports
+    for (i = 0; i < num_supported_formats; i++) {
+        // Iterate over all formats we support
+        for (j = 0; j < SDL_arraysize(SDLToVK_TextureFormat); j++) {
+            if (SDLToVK_TextureFormat[j] == supported_formats[i]) {
+                // Add the format match we found, linearly. The output order should match the order of the runtime.
+                sdl_formats[num_found_formats++] = j;
+                break;
             }
         }
     }
 
     SDL_stack_free(supported_formats);
 
-    if (vkFormat == VK_FORMAT_UNDEFINED) {
+    if (num_found_formats == 0) {
         SDL_SetError("Failed to find a swapchain format supported by both OpenXR and SDL");
+        SDL_stack_free(sdl_formats);
         return NULL;
     }
 
-    SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat*) SDL_malloc(sizeof(SDL_GPUTextureFormat) * 2);
-    retval[0] = sdlFormat;
-    retval[1] = SDL_GPU_TEXTUREFORMAT_INVALID;
-    *num_formats = 1;
+    SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat *)SDL_calloc((size_t)num_found_formats + 1, sizeof(SDL_GPUTextureFormat));
+    SDL_memcpy(retval, sdl_formats, sizeof(SDL_GPUTextureFormat) * num_found_formats); // Copy the translated formats
+    retval[num_found_formats] = SDL_GPU_TEXTUREFORMAT_INVALID; // Add a termination for good measure
+
+    *num_formats = num_found_formats;
+
+    SDL_stack_free(supported_formats);
+
     return retval;
 #else
     SDL_SetError("SDL not built with OpenXR support");

+ 18 - 4
test/testgpu_spinning_cube_xr.c

@@ -185,8 +185,8 @@ typedef struct {
     Uint32 image_count;
 } VRSwapchain;
 
-/* Depth buffer format - use D24 for wide compatibility */
-static const SDL_GPUTextureFormat DEPTH_FORMAT = SDL_GPU_TEXTUREFORMAT_D24_UNORM;
+/* Depth buffer format, default to D24, but fall down to D16 if D24 is unsupported on this hardware. */
+static SDL_GPUTextureFormat depth_format = SDL_GPU_TEXTUREFORMAT_D24_UNORM;
 
 static VRSwapchain *vr_swapchains = NULL;
 static XrView *xr_views = NULL;
@@ -392,7 +392,7 @@ static bool create_pipeline(SDL_GPUTextureFormat color_format)
                 .format = color_format
             }},
             .has_depth_stencil_target = true,
-            .depth_stencil_format = DEPTH_FORMAT
+            .depth_stencil_format = depth_format
         },
         .depth_stencil_state = {
             .enable_depth_test = true,
@@ -584,6 +584,15 @@ static bool create_swapchains(void)
     /* Use first available format (typically sRGB)
      * Note: Could iterate with: while (formats[i] != SDL_GPU_TEXTUREFORMAT_INVALID) */
     SDL_GPUTextureFormat swapchain_format = formats[0];
+
+    for (int i = 0; i < num_formats; i++) {
+        // Prefer an 8-bit sRGB format, if available, using the order the runtime wants first.
+        if (formats[i] == SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB || formats[i] == SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB) {
+            swapchain_format = formats[i];
+            break;
+        }
+    }
+
     SDL_Log("Using swapchain format: %d (of %d available)", swapchain_format, num_formats);
     
     /* Log all available formats for debugging */
@@ -592,6 +601,11 @@ static bool create_swapchains(void)
     }
     SDL_free(formats);
 
+    if (!SDL_GPUTextureSupportsFormat(gpu_device, depth_format, SDL_GPU_TEXTURETYPE_2D, SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
+        // This format is *guarenteed* to be supported.
+        depth_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
+    }
+
     for (Uint32 i = 0; i < view_count; i++) {
         xr_views[i].type = XR_TYPE_VIEW;
         xr_views[i].pose.orientation.w = 1.0f;
@@ -642,7 +656,7 @@ static bool create_swapchains(void)
          * for proper z-ordering without requiring XR_KHR_composition_layer_depth. */
         SDL_GPUTextureCreateInfo depth_info = {
             .type = SDL_GPU_TEXTURETYPE_2D,
-            .format = DEPTH_FORMAT,
+            .format = depth_format,
             .width = swapchain_info.width,
             .height = swapchain_info.height,
             .layer_count_or_depth = 1,