Skip to content

Commit

Permalink
gpu + openxr: Implement initial OpenXR support
Browse files Browse the repository at this point in the history
Currently only supports the SDL_gpu vulkan driver.
  • Loading branch information
Beyley committed Dec 22, 2024
1 parent ecea347 commit 0b64757
Show file tree
Hide file tree
Showing 14 changed files with 1,572 additions and 38 deletions.
23 changes: 23 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ set_option(SDL_ASAN "Use AddressSanitizer to detect memory errors
set_option(SDL_CCACHE "Use Ccache to speed up build" OFF)
set_option(SDL_CLANG_TIDY "Run clang-tidy static analysis" OFF)
set_option(SDL_GPU_DXVK "Build SDL_GPU with DXVK support" OFF)
set_option(SDL_GPU_OPENXR "Build SDL_GPU with OpenXR support" OFF)

set(SDL_VENDOR_INFO "" CACHE STRING "Vendor name and/or version to add to SDL_REVISION")

Expand Down Expand Up @@ -2993,6 +2994,28 @@ if(SDL_GPU)
set(SDL_VIDEO_RENDER_GPU 1)
set(HAVE_RENDER_GPU TRUE)
endif()
if(SDL_GPU_OPENXR)
# TODO: actually do this header detection correctly
set(HAVE_OPENXR_H TRUE)
# TODO: im not sure what the optimal way to do this is...
if(WIN32)
set(SDL_GPU_OPENXR_DYNAMIC "openxr_loader.dll")
elseif(APPLE)
set(SDL_GPU_OPENXR_DYNAMIC "libopenxr_loader.dylib")
else()
set(SDL_GPU_OPENXR_DYNAMIC "libopenxr_loader.so.1")
endif()
# if(PKG_CONFIG_FOUND)
# # pkg_search_module(OPENXR_LOADER openxr_loader)
# # if(OPENXR_LOADER_FOUND)
# # sdl_include_directories(PRIVATE SYSTEM ${OPENXR_LOADER_INCLUDE_DIRS})
# # endif()
# endif()
# endif()

sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/xr/*.c")
set(HAVE_GPU_OPENXR 1)
endif()
endif()

# Dummies
Expand Down
110 changes: 110 additions & 0 deletions include/SDL3/SDL_openxr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <[email protected]>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

/**
* # CategoryOpenXR
*
* Functions for creating OpenXR handles for SDL_gpu contexts.
*
* For the most part, OpenXR operates independent of SDL, but
* the graphics initialization depends on direct support from SDL_gpu.
*
*/

#ifndef SDL_openxr_h_
#define SDL_openxr_h_

#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_gpu.h>

#include <SDL3/SDL_begin_code.h>
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif

#if defined(OPENXR_H_)
#define NO_SDL_OPENXR_TYPEDEFS 1
#endif /* OPENXR_H_ */

#if !defined(NO_SDL_OPENXR_TYPEDEFS)
#define XR_NULL_HANDLE 0

#if !defined(XR_DEFINE_HANDLE)
#define XR_DEFINE_HANDLE(object) typedef Uint64 object;
#endif /* XR_DEFINE_HANDLE */

XR_DEFINE_HANDLE(XrInstance)
XR_DEFINE_HANDLE(XrSystemId)
XR_DEFINE_HANDLE(XrSession)
XR_DEFINE_HANDLE(XrSwapchain)

typedef struct {} XrSessionCreateInfo;
typedef struct {} XrSwapchainCreateInfo;

typedef enum XrResult {
XR_ERROR_FUNCTION_UNSUPPORTED = -7,
XR_ERROR_HANDLE_INVALID = -12,
} XrResult;
#endif /* NO_SDL_OPENXR_TYPEDEFS */

extern SDL_DECLSPEC bool SDLCALL SDL_CreateXRGPUDeviceWithProperties(
SDL_GPUDevice **device,
XrInstance *instance,
XrSystemId *systemId,
SDL_PropertiesID props);

#define SDL_PROP_GPU_DEVICE_CREATE_XR_VERSION "SDL.gpu.device.create.xr.version"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_COUNT "SDL.gpu.device.create.xr.extensions.count"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_NAMES "SDL.gpu.device.create.xr.extensions.names"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_COUNT "SDL.gpu.device.create.xr.layers.count"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_NAMES "SDL.gpu.device.create.xr.layers.names"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_NAME "SDL.gpu.device.create.xr.application.name"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_VERSION "SDL.gpu.device.create.xr.application.version"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_NAME "SDL.gpu.device.create.xr.engine.name"
#define SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_VERSION "SDL.gpu.device.create.xr.engine.version"

extern SDL_DECLSPEC XrResult SDLCALL SDL_CreateGPUXRSession(
SDL_GPUDevice *device,
const XrSessionCreateInfo *createinfo,
XrSession *session);

/* TODO: document this. tl;dr: SDL_gpu picks the format,
and validates the usageFlags are supported by SDL_gpu,
but all other fields are fair game */
/* TODO: figure out then document what usageFlags are actually possible to be supported by SDL_gpu */
extern SDL_DECLSPEC XrResult SDLCALL SDL_CreateGPUXRSwapchain(
SDL_GPUDevice *device,
XrSession session,
const XrSwapchainCreateInfo *createinfo, /* your normal create info sans the format */
SDL_GPUTextureFormat *textureFormat, /* the texture format chosen by SDL_gpu */
XrSwapchain *swapchain, /* the created swapchain */
SDL_GPUTexture ***textures /* ptr to where an array of SDL_GPUTexture you can render to will be */);

extern SDL_DECLSPEC XrResult SDLCALL SDL_DestroyGPUXRSwapchain(SDL_GPUDevice *device, XrSwapchain swapchain, SDL_GPUTexture **swapchainImages);

/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include <SDL3/SDL_close_code.h>

#endif /* SDL_openxr_h_ */
2 changes: 2 additions & 0 deletions include/build_config/SDL_build_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,8 @@
#cmakedefine SDL_GPU_D3D12 @SDL_GPU_D3D12@
#cmakedefine SDL_GPU_VULKAN @SDL_GPU_VULKAN@
#cmakedefine SDL_GPU_METAL @SDL_GPU_METAL@
#cmakedefine HAVE_GPU_OPENXR @HAVE_GPU_OPENXR@
#cmakedefine SDL_GPU_OPENXR_DYNAMIC "@SDL_GPU_OPENXR_DYNAMIC@"

/* Enable system power support */
#cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
Expand Down
1 change: 1 addition & 0 deletions src/SDL_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
#undef SDL_GPU_D3D12
#undef SDL_GPU_METAL
#undef SDL_GPU_VULKAN
#undef HAVE_GPU_OPENXR
#undef SDL_VIDEO_RENDER_GPU
#endif // SDL_GPU_DISABLED

Expand Down
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#endif

#include <SDL3/SDL.h>
#include <SDL3/SDL_openxr.h>
#define SDL_MAIN_NOIMPL // don't drag in header-only implementation of SDL_main
#include <SDL3/SDL_main.h>

Expand Down Expand Up @@ -556,6 +557,7 @@ static void SDL_InitDynamicAPI(void)
#else // SDL_DYNAMIC_API

#include <SDL3/SDL.h>
#include <SDL3/SDL_openxr.h>

Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize);
Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize)
Expand Down
4 changes: 4 additions & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,10 @@ SDL3_0.0.0 {
SDL_RenderTextureAffine;
SDL_WaitAndAcquireGPUSwapchainTexture;
SDL_RenderDebugTextFormat;
SDL_CreateXRGPUDeviceWithProperties;
SDL_CreateGPUXRSession;
SDL_CreateGPUXRSwapchain;
SDL_DestroyGPUXRSwapchain;
# extra symbols go here (don't modify this line)
local: *;
};
4 changes: 4 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1233,3 +1233,7 @@
#define SDL_RenderTextureAffine SDL_RenderTextureAffine_REAL
#define SDL_WaitAndAcquireGPUSwapchainTexture SDL_WaitAndAcquireGPUSwapchainTexture_REAL
#define SDL_RenderDebugTextFormat SDL_RenderDebugTextFormat_REAL
#define SDL_CreateXRGPUDeviceWithProperties SDL_CreateXRGPUDeviceWithProperties_REAL
#define SDL_CreateGPUXRSession SDL_CreateGPUXRSession_REAL
#define SDL_CreateGPUXRSwapchain SDL_CreateGPUXRSwapchain_REAL
#define SDL_DestroyGPUXRSwapchain SDL_DestroyGPUXRSwapchain_REAL
4 changes: 4 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1241,3 +1241,7 @@ SDL_DYNAPI_PROC(bool,SDL_WaitAndAcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer
#ifndef SDL_DYNAPI_PROC_NO_VARARGS
SDL_DYNAPI_PROC(bool,SDL_RenderDebugTextFormat,(SDL_Renderer *a,float b,float c,SDL_PRINTF_FORMAT_STRING const char *d,...),(a,b,c,d),return)
#endif
SDL_DYNAPI_PROC(bool,SDL_CreateXRGPUDeviceWithProperties,(SDL_GPUDevice **a, XrInstance *b, XrSystemId *c, SDL_PropertiesID d),(a,b,c,d),return)
SDL_DYNAPI_PROC(XrResult,SDL_CreateGPUXRSession,(SDL_GPUDevice *a, const XrSessionCreateInfo *b, XrSession *c),(a,b,c),return)
SDL_DYNAPI_PROC(XrResult,SDL_CreateGPUXRSwapchain,(SDL_GPUDevice *a, XrSession b, const XrSwapchainCreateInfo *c, SDL_GPUTextureFormat *d, XrSwapchain *e, SDL_GPUTexture ***f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(XrResult,SDL_DestroyGPUXRSwapchain,(SDL_GPUDevice *a,XrSwapchain b,SDL_GPUTexture **c),(a,b,c),return)
65 changes: 65 additions & 0 deletions src/gpu/SDL_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,37 @@ SDL_GPUDevice *SDL_CreateGPUDevice(
#endif // SDL_GPU_DISABLED
}

bool SDL_CreateXRGPUDeviceWithProperties(
SDL_GPUDevice **device,
XrInstance *instance,
XrSystemId *systemId,
SDL_PropertiesID props)
{
#ifndef SDL_GPU_DISABLED
bool debug_mode;
bool preferLowPower;
const SDL_GPUBootstrap *selectedBackend;

/* TODO: make the backend selection actually take the available OpenXR instance extensions into account */
selectedBackend = SDL_GPUSelectBackend(props);
if (selectedBackend != NULL) {
debug_mode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, true);
preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, false);

if (selectedBackend->CreateXrDevice(device, instance, systemId, debug_mode, preferLowPower, props)) {
(*device)->backend = selectedBackend->name;
(*device)->shader_formats = selectedBackend->shader_formats;
(*device)->debug_mode = debug_mode;
return true;
}
}
return false;
#else
SDL_SetError("SDL not built with GPU support");
return false;
#endif // SDL_GPU_DISABLED
}

SDL_GPUDevice *SDL_CreateGPUDeviceWithProperties(SDL_PropertiesID props)
{
#ifndef SDL_GPU_DISABLED
Expand Down Expand Up @@ -547,6 +578,17 @@ void SDL_DestroyGPUDevice(SDL_GPUDevice *device)
device->DestroyDevice(device);
}

XrResult SDL_DestroyGPUXRSwapchain(SDL_GPUDevice *device, XrSwapchain swapchain, SDL_GPUTexture **swapchainImages)
{
#ifdef HAVE_GPU_OPENXR
CHECK_DEVICE_MAGIC(device, XR_ERROR_HANDLE_INVALID);

return device->DestroyXRSwapchain(device->driverData, swapchain, swapchainImages);
#else
return XR_ERROR_FUNCTION_UNSUPPORTED;
#endif
}

int SDL_GetNumGPUDrivers(void)
{
#ifndef SDL_GPU_DISABLED
Expand Down Expand Up @@ -2919,3 +2961,26 @@ Uint32 SDL_CalculateGPUTextureFormatSize(
Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight;
return depth_or_layer_count * blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format);
}

XrResult SDL_CreateGPUXRSession(
SDL_GPUDevice *device,
const XrSessionCreateInfo *createinfo,
XrSession *session)
{
CHECK_DEVICE_MAGIC(device, XR_NULL_HANDLE);

return device->CreateXRSession(device->driverData, createinfo, session);
}

XrResult SDL_CreateGPUXRSwapchain(
SDL_GPUDevice *device,
XrSession session,
const XrSwapchainCreateInfo *createinfo,
SDL_GPUTextureFormat *textureFormat,
XrSwapchain *swapchain,
SDL_GPUTexture ***textures)
{
CHECK_DEVICE_MAGIC(device, XR_NULL_HANDLE);

return device->CreateXRSwapchain(device->driverData, session, createinfo, textureFormat, swapchain, textures);
}
24 changes: 24 additions & 0 deletions src/gpu/SDL_sysgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#ifndef SDL_GPU_DRIVER_H
#define SDL_GPU_DRIVER_H

#include <SDL3/SDL_openxr.h>

// Common Structs

typedef struct Pass
Expand Down Expand Up @@ -449,6 +451,11 @@ struct SDL_GPUDevice

void (*DestroyDevice)(SDL_GPUDevice *device);

XrResult (*DestroyXRSwapchain)(
SDL_GPURenderer *device,
XrSwapchain swapchain,
SDL_GPUTexture **swapchainImages);

// State Creation

SDL_GPUComputePipeline *(*CreateComputePipeline)(
Expand Down Expand Up @@ -481,6 +488,19 @@ struct SDL_GPUDevice
SDL_GPUTransferBufferUsage usage,
Uint32 size);

XrResult (*CreateXRSession)(
SDL_GPURenderer *driverData,
const XrSessionCreateInfo *createinfo,
XrSession *session);

XrResult (*CreateXRSwapchain)(
SDL_GPURenderer *driverData,
XrSession session,
const XrSwapchainCreateInfo *createinfo,
SDL_GPUTextureFormat *textureFormat,
XrSwapchain *swapchain,
SDL_GPUTexture ***textures);

// Debug Naming

void (*SetBufferName)(
Expand Down Expand Up @@ -878,13 +898,16 @@ struct SDL_GPUDevice
result->func = name##_##func;
#define ASSIGN_DRIVER(name) \
ASSIGN_DRIVER_FUNC(DestroyDevice, name) \
ASSIGN_DRIVER_FUNC(DestroyXRSwapchain, name) \
ASSIGN_DRIVER_FUNC(CreateComputePipeline, name) \
ASSIGN_DRIVER_FUNC(CreateGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(CreateSampler, name) \
ASSIGN_DRIVER_FUNC(CreateShader, name) \
ASSIGN_DRIVER_FUNC(CreateTexture, name) \
ASSIGN_DRIVER_FUNC(CreateBuffer, name) \
ASSIGN_DRIVER_FUNC(CreateTransferBuffer, name) \
ASSIGN_DRIVER_FUNC(CreateXRSession, name) \
ASSIGN_DRIVER_FUNC(CreateXRSwapchain, name) \
ASSIGN_DRIVER_FUNC(SetBufferName, name) \
ASSIGN_DRIVER_FUNC(SetTextureName, name) \
ASSIGN_DRIVER_FUNC(InsertDebugLabel, name) \
Expand Down Expand Up @@ -966,6 +989,7 @@ typedef struct SDL_GPUBootstrap
const SDL_GPUShaderFormat shader_formats;
bool (*PrepareDriver)(SDL_VideoDevice *_this);
SDL_GPUDevice *(*CreateDevice)(bool debug_mode, bool prefer_low_power, SDL_PropertiesID props);
bool (*CreateXrDevice)(SDL_GPUDevice **gpu_device, XrInstance *xrInstance, XrSystemId *xrSystemId, bool debug_mode, bool prefer_low_power, SDL_PropertiesID props);
} SDL_GPUBootstrap;

#ifdef __cplusplus
Expand Down
Loading

0 comments on commit 0b64757

Please sign in to comment.