work on basic VR
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -34,3 +34,6 @@
|
|||||||
[submodule "external/SPIRV-Headers"]
|
[submodule "external/SPIRV-Headers"]
|
||||||
path = external/SPIRV-Headers
|
path = external/SPIRV-Headers
|
||||||
url = https://github.com/KhronosGroup/SPIRV-Headers
|
url = https://github.com/KhronosGroup/SPIRV-Headers
|
||||||
|
[submodule "external/OpenXR-SDK"]
|
||||||
|
path = external/OpenXR-SDK
|
||||||
|
url = https://github.com/KhronosGroup/OpenXR-SDK
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ DECLARE_BUILD_STAGE(engine)
|
|||||||
"miniaudio.cpp",
|
"miniaudio.cpp",
|
||||||
|
|
||||||
"kottui.cpp",
|
"kottui.cpp",
|
||||||
|
|
||||||
|
"openxr.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( GET_PROJECT_VALUE(config, "steam") == "true" )
|
if ( GET_PROJECT_VALUE(config, "steam") == "true" )
|
||||||
@@ -43,6 +45,8 @@ DECLARE_BUILD_STAGE(engine)
|
|||||||
"../external/cglm/include",
|
"../external/cglm/include",
|
||||||
FUNNYSTDLIB"public",
|
FUNNYSTDLIB"public",
|
||||||
EXTERNAL"steamworks/public",
|
EXTERNAL"steamworks/public",
|
||||||
|
EXTERNAL"Vulkan-Headers/include",
|
||||||
|
EXTERNAL"Vulkan-Utility-Libraries/include",
|
||||||
EXTERNAL
|
EXTERNAL
|
||||||
};
|
};
|
||||||
if ( GET_PROJECT_VALUE(config, "steam") == "true" )
|
if ( GET_PROJECT_VALUE(config, "steam") == "true" )
|
||||||
@@ -81,6 +85,7 @@ DECLARE_BUILD_STAGE(engine)
|
|||||||
ldProject.libraries.AppendTail("shell32");
|
ldProject.libraries.AppendTail("shell32");
|
||||||
ldProject.libraries.AppendTail("uuid");
|
ldProject.libraries.AppendTail("uuid");
|
||||||
};
|
};
|
||||||
|
ldProject.libraries.AppendTail("openxr_loader");
|
||||||
|
|
||||||
CUtlString outputProject = linker->Link(&ldProject);
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ extern "C" void FunnyMain( int argc, char **argv )
|
|||||||
pWindow->SetAxisCallback(CallAxisEvent);
|
pWindow->SetAxisCallback(CallAxisEvent);
|
||||||
|
|
||||||
g_pRenderContext = (IRenderContext*)pRenderSystemFactory(RENDER_CONTEXT_INTERFACE_VERSION, NULL);
|
g_pRenderContext = (IRenderContext*)pRenderSystemFactory(RENDER_CONTEXT_INTERFACE_VERSION, NULL);
|
||||||
g_pRenderContext->SetMainWindowManager(g_pWindowManager);
|
g_pRenderContext->ConnectInterface(g_pWindowManager, GAME_WINDOW_MANAGER_INTERFACE_VERSION);
|
||||||
g_pRenderContext->Init();
|
g_pRenderContext->Init();
|
||||||
|
|
||||||
g_pRenderContext->RegisterGameWindow(pWindow);
|
g_pRenderContext->RegisterGameWindow(pWindow);
|
||||||
|
|||||||
498
engine/openxr.cpp
Normal file
498
engine/openxr.cpp
Normal file
@@ -0,0 +1,498 @@
|
|||||||
|
#include "ixr.h"
|
||||||
|
#include "openxr/openxr.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
#undef __cplusplus
|
||||||
|
#include "vulkan/vk_enum_string_helper.h"
|
||||||
|
#define __cplusplus 202400L
|
||||||
|
#define XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
#include "openxr/openxr_platform.h"
|
||||||
|
#include "tier0/lib.h"
|
||||||
|
#include "tier1/utlvector.h"
|
||||||
|
#include "materialsystem/imaterialsystem.h"
|
||||||
|
|
||||||
|
struct EyeSwapchain_t
|
||||||
|
{
|
||||||
|
XrSwapchain m_swapchain;
|
||||||
|
uint32_t m_uWidth;
|
||||||
|
uint32_t m_uHeight;
|
||||||
|
uint32_t m_uImageIndex;
|
||||||
|
CUtlVector<IImage*> m_pImages;
|
||||||
|
IImage *m_pUserImage;
|
||||||
|
};
|
||||||
|
|
||||||
|
class COpenXRManager;
|
||||||
|
class COpenXRHeadset: public IXRHeadset, public IAppSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Init() override;
|
||||||
|
virtual void Shutdown() override;
|
||||||
|
|
||||||
|
virtual uint32_t GetSurfaceCount() override;
|
||||||
|
virtual XRRenderSurface_t GetSurface( uint32_t i ) override;
|
||||||
|
virtual void SetSurfaceImage( uint32_t i, IImage *pImage ) override;
|
||||||
|
|
||||||
|
void Frame();
|
||||||
|
void BeforeRender();
|
||||||
|
void AfterRender();
|
||||||
|
void CopySwapchain();
|
||||||
|
void CreateSwapchainForEye( XrViewConfigurationView *pConf, VkFormat eVkFormat, EyeSwapchain_t *pEye );
|
||||||
|
|
||||||
|
COpenXRManager *m_pManager;
|
||||||
|
XrSystemId m_systemId;
|
||||||
|
XrSession m_session;
|
||||||
|
XrSpace m_space;
|
||||||
|
|
||||||
|
CUtlVector<EyeSwapchain_t> m_eyeSwapchains;
|
||||||
|
CUtlVector<XrCompositionLayerProjectionView> m_projviews;
|
||||||
|
CUtlVector<XrView> m_views;
|
||||||
|
float m_fPredictedTime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class COpenXRController: public IXRController
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class COpenXRManager: public IXRManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Init() override;
|
||||||
|
virtual void Shutdown() override;
|
||||||
|
virtual void ConnectInterface( void *pIface, const char *szName ) override;
|
||||||
|
virtual void Frame() override;
|
||||||
|
virtual void PreRender() override;
|
||||||
|
virtual void PostRender() override;
|
||||||
|
virtual void CopySwapchain() override;
|
||||||
|
|
||||||
|
virtual uint32_t GetHeadsetCount() override;
|
||||||
|
virtual IXRHeadset *GetHeadset( uint32_t i ) override;
|
||||||
|
|
||||||
|
IRenderContext *m_pRenderContext;
|
||||||
|
COpenXRHeadset m_headset;
|
||||||
|
|
||||||
|
XrInstance m_instance;
|
||||||
|
};
|
||||||
|
EXPOSE_INTERFACE(COpenXRManager, IXRManager, OPEN_XR_INTERFACE_VERSION);
|
||||||
|
|
||||||
|
void COpenXRManager::Init()
|
||||||
|
{
|
||||||
|
PFN_xrInitializeLoaderKHR fnInitLoader = NULL;
|
||||||
|
XrResult r = xrGetInstanceProcAddr(NULL, "xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&fnInitLoader);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("Failed to load OpenXR");
|
||||||
|
XrApplicationInfo appInfo = {};
|
||||||
|
appInfo.apiVersion = XR_API_VERSION_1_1;
|
||||||
|
V_strncpy(appInfo.applicationName, "funny", XR_MAX_APPLICATION_NAME_SIZE);
|
||||||
|
V_strncpy(appInfo.engineName, "funny", XR_MAX_ENGINE_NAME_SIZE);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("Failed to load OpenXR\n");
|
||||||
|
const char *extensions[] = {
|
||||||
|
XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||||
|
XR_KHR_VULKAN_ENABLE_EXTENSION_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *layers[] = {
|
||||||
|
"XR_APILAYER_LUNARG_core_validation"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
XrInstanceCreateInfo createInfo = {};
|
||||||
|
createInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
createInfo.applicationInfo = appInfo;
|
||||||
|
createInfo.enabledExtensionCount = sizeof(extensions)/sizeof(*extensions);
|
||||||
|
createInfo.enabledExtensionNames = extensions;
|
||||||
|
createInfo.enabledApiLayerCount = sizeof(layers)/sizeof(*layers);
|
||||||
|
createInfo.enabledApiLayerNames = layers;
|
||||||
|
r = xrCreateInstance(&createInfo, &m_instance);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("xrCreateInstance\n");
|
||||||
|
|
||||||
|
m_headset.m_pManager = this;
|
||||||
|
m_headset.Init();
|
||||||
|
|
||||||
|
XrInstanceProperties props = {};
|
||||||
|
props.type = XR_TYPE_INSTANCE_PROPERTIES;
|
||||||
|
xrGetInstanceProperties(m_instance, &props);
|
||||||
|
V_printf("OpenXR runtime: %s\n", props.runtimeName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRManager::Shutdown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void COpenXRManager::Frame()
|
||||||
|
{
|
||||||
|
m_headset.Frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRManager::PreRender()
|
||||||
|
{
|
||||||
|
m_headset.BeforeRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRManager::PostRender()
|
||||||
|
{
|
||||||
|
m_headset.AfterRender();
|
||||||
|
}
|
||||||
|
void COpenXRManager::CopySwapchain()
|
||||||
|
{
|
||||||
|
m_headset.CopySwapchain();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void COpenXRHeadset::Init()
|
||||||
|
{
|
||||||
|
|
||||||
|
XrSystemGetInfo sgi = {};
|
||||||
|
XrResult r;
|
||||||
|
sgi.type = XR_TYPE_SYSTEM_GET_INFO;
|
||||||
|
sgi.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
||||||
|
r = xrGetSystem(m_pManager->m_instance, &sgi, &m_systemId);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("xrGetSystem\n");
|
||||||
|
|
||||||
|
|
||||||
|
XrGraphicsRequirementsVulkanKHR requirements = {};
|
||||||
|
requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
|
||||||
|
PFN_xrGetVulkanGraphicsRequirementsKHR fnVulkanRequirements = NULL;
|
||||||
|
xrGetInstanceProcAddr(m_pManager->m_instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&fnVulkanRequirements);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("Failed to get xrGetVulkanGraphicsRequirementsKHR\n");
|
||||||
|
fnVulkanRequirements( m_pManager->m_instance, m_systemId, &requirements);
|
||||||
|
|
||||||
|
|
||||||
|
PFN_xrGetVulkanGraphicsDeviceKHR fnVulkanDevice = NULL;
|
||||||
|
xrGetInstanceProcAddr(m_pManager->m_instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction*)&fnVulkanDevice);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("Failed to get xrGetVulkanGraphicsDeviceKHR\n");
|
||||||
|
VkPhysicalDevice d = NULL;
|
||||||
|
fnVulkanDevice(m_pManager->m_instance, m_systemId, (VkInstance)m_pManager->m_pRenderContext->GetVulkanInstance(), &d);
|
||||||
|
|
||||||
|
XrGraphicsBindingVulkan2KHR vkBinding = {};
|
||||||
|
vkBinding.type = XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR;
|
||||||
|
vkBinding.instance = (VkInstance)m_pManager->m_pRenderContext->GetVulkanInstance();
|
||||||
|
vkBinding.physicalDevice = (VkPhysicalDevice)m_pManager->m_pRenderContext->GetVulkanPhysicalDevice();
|
||||||
|
vkBinding.device = (VkDevice)m_pManager->m_pRenderContext->GetVulkanDevice();
|
||||||
|
|
||||||
|
XrSessionCreateInfo sessionCreateInfo = {};
|
||||||
|
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
|
||||||
|
sessionCreateInfo.next = &vkBinding;
|
||||||
|
sessionCreateInfo.systemId = m_systemId;
|
||||||
|
r = xrCreateSession(m_pManager->m_instance, &sessionCreateInfo, &m_session);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("xrCreateSession\n");
|
||||||
|
|
||||||
|
/* create swapchains for rendering pipeline */
|
||||||
|
|
||||||
|
uint32_t formatCount = 0;
|
||||||
|
xrEnumerateSwapchainFormats(m_session, 0, &formatCount, NULL);
|
||||||
|
|
||||||
|
CUtlVector<int64_t> formats = formatCount;
|
||||||
|
xrEnumerateSwapchainFormats(m_session, formatCount, &formatCount, formats.GetData());
|
||||||
|
|
||||||
|
const VkFormat preferedSurfaceFormats[] = {
|
||||||
|
VK_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
VK_FORMAT_R8G8B8A8_SRGB,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkFormat eSelectedFormat = preferedSurfaceFormats[0];
|
||||||
|
for (auto &format: formats)
|
||||||
|
{
|
||||||
|
V_printf("Format: %s\n", string_VkFormat((VkFormat)format));
|
||||||
|
for (int i = 0; i < sizeof(preferedSurfaceFormats)/sizeof(VkFormat); i++)
|
||||||
|
{
|
||||||
|
if (format == preferedSurfaceFormats[i])
|
||||||
|
{
|
||||||
|
eSelectedFormat = preferedSurfaceFormats[i];
|
||||||
|
goto formatPicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formatPicked:
|
||||||
|
|
||||||
|
uint32_t viewCount = 0;
|
||||||
|
xrEnumerateViewConfigurationViews(m_pManager->m_instance, m_systemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &viewCount, NULL);
|
||||||
|
CUtlVector<XrViewConfigurationView> views = viewCount;
|
||||||
|
for ( auto &v: views )
|
||||||
|
{
|
||||||
|
v.type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
|
||||||
|
}
|
||||||
|
xrEnumerateViewConfigurationViews(m_pManager->m_instance, m_systemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, viewCount, &viewCount, views.GetData());
|
||||||
|
|
||||||
|
for ( auto &v: views )
|
||||||
|
{
|
||||||
|
m_eyeSwapchains.AppendTail((EyeSwapchain_t){});
|
||||||
|
CreateSwapchainForEye(&v, eSelectedFormat, m_eyeSwapchains.GetData() + m_eyeSwapchains.GetSize() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrReferenceSpaceCreateInfo spaceInfo = {};
|
||||||
|
spaceInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||||
|
spaceInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
|
spaceInfo.poseInReferenceSpace = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}};
|
||||||
|
xrCreateReferenceSpace(m_session, &spaceInfo, &m_space);
|
||||||
|
m_fPredictedTime = 0;
|
||||||
|
m_views = m_eyeSwapchains.GetSize();
|
||||||
|
m_projviews = m_eyeSwapchains.GetSize();
|
||||||
|
for ( auto &v: m_views )
|
||||||
|
{
|
||||||
|
v = {};
|
||||||
|
v.type = XR_TYPE_VIEW;
|
||||||
|
}
|
||||||
|
for ( auto &v: m_projviews )
|
||||||
|
{
|
||||||
|
v = {};
|
||||||
|
v.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrViewState viewState = {};
|
||||||
|
viewState.type = XR_TYPE_VIEW_STATE;
|
||||||
|
XrViewLocateInfo viewLocale = {};
|
||||||
|
viewLocale.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||||
|
viewLocale.displayTime = m_fPredictedTime;
|
||||||
|
viewLocale.space = m_space;
|
||||||
|
viewLocale.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
||||||
|
uint32_t vc = m_views.GetSize();
|
||||||
|
xrLocateViews(m_session, &viewLocale, &viewState, vc, &vc, m_views.GetData());
|
||||||
|
|
||||||
|
}
|
||||||
|
void COpenXRHeadset::Shutdown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRHeadset::Frame()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
XrEventDataBuffer event = {};
|
||||||
|
event.type = XR_TYPE_EVENT_DATA_BUFFER;
|
||||||
|
XrResult r = xrPollEvent(m_pManager->m_instance, &event);
|
||||||
|
if ( r != XR_SUCCESS )
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
|
||||||
|
{
|
||||||
|
XrEventDataSessionStateChanged *e = (XrEventDataSessionStateChanged*)&event;
|
||||||
|
if ( e->state == XR_SESSION_STATE_READY )
|
||||||
|
{
|
||||||
|
XrSessionBeginInfo beginInfo = {};
|
||||||
|
beginInfo.type = XR_TYPE_SESSION_BEGIN_INFO;
|
||||||
|
beginInfo.primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
||||||
|
xrBeginSession(m_session, &beginInfo);
|
||||||
|
}
|
||||||
|
if ( e->state == XR_SESSION_STATE_STOPPING )
|
||||||
|
{
|
||||||
|
xrEndSession(m_session);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
XrFrameWaitInfo frameWait = {};
|
||||||
|
XrFrameState frameState = {};
|
||||||
|
frameState.type = XR_TYPE_FRAME_STATE;
|
||||||
|
frameWait.type = XR_TYPE_FRAME_WAIT_INFO;
|
||||||
|
xrWaitFrame(m_session, &frameWait, &frameState);
|
||||||
|
m_fPredictedTime = frameState.predictedDisplayTime;
|
||||||
|
|
||||||
|
|
||||||
|
m_views = m_eyeSwapchains.GetSize();
|
||||||
|
m_projviews = m_eyeSwapchains.GetSize();
|
||||||
|
for ( auto &v: m_views )
|
||||||
|
{
|
||||||
|
v = {};
|
||||||
|
v.type = XR_TYPE_VIEW;
|
||||||
|
}
|
||||||
|
for ( auto &v: m_projviews )
|
||||||
|
{
|
||||||
|
v = {};
|
||||||
|
v.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrViewState viewState = {};
|
||||||
|
viewState.type = XR_TYPE_VIEW_STATE;
|
||||||
|
XrViewLocateInfo viewLocale = {};
|
||||||
|
viewLocale.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||||
|
viewLocale.displayTime = m_fPredictedTime;
|
||||||
|
viewLocale.space = m_space;
|
||||||
|
viewLocale.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
||||||
|
uint32_t viewCount = m_views.GetSize();
|
||||||
|
xrLocateViews(m_session, &viewLocale, &viewState, viewCount, &viewCount, m_views.GetData());
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRHeadset::BeforeRender()
|
||||||
|
{
|
||||||
|
|
||||||
|
XrFrameBeginInfo begin = {};
|
||||||
|
begin.type = XR_TYPE_FRAME_BEGIN_INFO;
|
||||||
|
xrBeginFrame(m_session, &begin);
|
||||||
|
for ( uint32_t i = 0; i < m_views.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
XrSwapchainImageAcquireInfo acq = {};
|
||||||
|
acq.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
|
||||||
|
uint32_t idx = 0;
|
||||||
|
XrResult r = xrAcquireSwapchainImage(m_eyeSwapchains[i].m_swapchain, &acq, &idx);
|
||||||
|
m_eyeSwapchains[i].m_uImageIndex = idx;
|
||||||
|
if (r) return;
|
||||||
|
XrSwapchainImageWaitInfo wait = {};
|
||||||
|
wait.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
|
||||||
|
wait.timeout = XR_INFINITE_DURATION;
|
||||||
|
xrWaitSwapchainImage(m_eyeSwapchains[i].m_swapchain, &wait);
|
||||||
|
|
||||||
|
m_projviews[i].fov = m_views[i].fov;
|
||||||
|
m_projviews[i].pose = m_views[i].pose;
|
||||||
|
m_projviews[i].subImage.swapchain = m_eyeSwapchains[i].m_swapchain;
|
||||||
|
m_projviews[i].subImage.imageRect.extent.height = m_eyeSwapchains[i].m_pImages[idx]->GetImageWidth();
|
||||||
|
m_projviews[i].subImage.imageRect.extent.width = m_eyeSwapchains[i].m_pImages[idx]->GetImageHeight();
|
||||||
|
m_projviews[i].subImage.imageArrayIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void COpenXRHeadset::CopySwapchain()
|
||||||
|
{
|
||||||
|
IRenderContext *pCtx = m_pManager->m_pRenderContext;
|
||||||
|
IRenderCommandList *pList = pCtx->CreateCommandList();
|
||||||
|
pList->StartRecording();
|
||||||
|
for ( auto &eye: m_eyeSwapchains)
|
||||||
|
{
|
||||||
|
ImageSector_t sector = {};
|
||||||
|
sector.m_iWidth = eye.m_uWidth;
|
||||||
|
sector.m_iHeight = eye.m_uHeight;
|
||||||
|
pList->BlitImageToImage(eye.m_pUserImage, sector, eye.m_pImages[eye.m_uImageIndex], sector);
|
||||||
|
}
|
||||||
|
pList->EndRecording();
|
||||||
|
pCtx->SubmitCommandList(pList);
|
||||||
|
pCtx->DestroyCommandList(pList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRHeadset::AfterRender()
|
||||||
|
{
|
||||||
|
for ( uint32_t i = 0; i < m_views.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
XrSwapchainImageReleaseInfo rel = {};
|
||||||
|
rel.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO;
|
||||||
|
xrReleaseSwapchainImage(m_eyeSwapchains[i].m_swapchain, &rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrCompositionLayerProjection proj = {};
|
||||||
|
proj.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
||||||
|
proj.space = m_space;
|
||||||
|
proj.viewCount = m_projviews.GetSize();
|
||||||
|
proj.views = m_projviews.GetData();
|
||||||
|
XrCompositionLayerBaseHeader *compositions[] = {
|
||||||
|
(XrCompositionLayerBaseHeader*)&proj
|
||||||
|
};
|
||||||
|
|
||||||
|
XrFrameEndInfo end = {};
|
||||||
|
end.type = XR_TYPE_FRAME_END_INFO;
|
||||||
|
end.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
|
||||||
|
end.layerCount = 1;
|
||||||
|
end.layers = compositions;
|
||||||
|
end.displayTime = m_fPredictedTime;
|
||||||
|
xrEndFrame(m_session, &end);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t COpenXRHeadset::GetSurfaceCount()
|
||||||
|
{
|
||||||
|
V_printf("%i\n", m_eyeSwapchains.GetSize());
|
||||||
|
return m_eyeSwapchains.GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRenderSurface_t COpenXRHeadset::GetSurface( uint32_t i )
|
||||||
|
{
|
||||||
|
XRRenderSurface_t surface = {};
|
||||||
|
surface.m_fFov = m_projviews[i].fov.angleLeft+m_projviews[i].fov.angleRight;
|
||||||
|
surface.m_uWidth = m_eyeSwapchains[i].m_uWidth;
|
||||||
|
surface.m_uHeight = m_eyeSwapchains[i].m_uHeight;
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRHeadset::SetSurfaceImage( uint32_t i, IImage *pImage )
|
||||||
|
{
|
||||||
|
m_eyeSwapchains[i].m_pUserImage = pImage;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRHeadset::CreateSwapchainForEye( XrViewConfigurationView *pConf, VkFormat eVkFormat, EyeSwapchain_t *pEye )
|
||||||
|
{
|
||||||
|
XrSwapchainCreateInfo createInfo = {};
|
||||||
|
createInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
|
||||||
|
createInfo.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT;
|
||||||
|
createInfo.format = eVkFormat;
|
||||||
|
createInfo.sampleCount = pConf->recommendedSwapchainSampleCount;
|
||||||
|
createInfo.width = pConf->recommendedImageRectWidth;
|
||||||
|
createInfo.height = pConf->recommendedImageRectHeight;
|
||||||
|
createInfo.faceCount = 1;
|
||||||
|
createInfo.arraySize = 1;
|
||||||
|
createInfo.mipCount = 1;
|
||||||
|
XrResult r = xrCreateSwapchain(m_session, &createInfo, &pEye->m_swapchain);
|
||||||
|
if (r != XR_SUCCESS)
|
||||||
|
Plat_FatalErrorFunc("xrCreateSwapchain\n");
|
||||||
|
pEye->m_uWidth = pConf->recommendedImageRectWidth;
|
||||||
|
pEye->m_uHeight = pConf->recommendedImageRectHeight;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t imageCount = 0;
|
||||||
|
xrEnumerateSwapchainImages(pEye->m_swapchain, 0, &imageCount, NULL);
|
||||||
|
CUtlVector<XrSwapchainImageVulkan2KHR> images = imageCount;
|
||||||
|
for ( auto &i: images )
|
||||||
|
{
|
||||||
|
i.type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR;
|
||||||
|
}
|
||||||
|
xrEnumerateSwapchainImages(pEye->m_swapchain, imageCount, &imageCount, (XrSwapchainImageBaseHeader*)images.GetData());
|
||||||
|
pEye->m_pImages = imageCount;
|
||||||
|
|
||||||
|
EImageFormat eFormat = IMAGE_FORMAT_RGBA8_UNORM;
|
||||||
|
switch(eVkFormat)
|
||||||
|
{
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM: eFormat = IMAGE_FORMAT_RGBA8_UNORM; break;
|
||||||
|
case VK_FORMAT_B8G8R8A8_UNORM: eFormat = IMAGE_FORMAT_BGRA8_UNORM; break;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SRGB: eFormat = IMAGE_FORMAT_RGBA8_SRGB; break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
for ( int i = 0; i < imageCount; i++ )
|
||||||
|
{
|
||||||
|
pEye->m_pImages[i] = m_pManager->m_pRenderContext->CreateImageFromVkImage(
|
||||||
|
images[i].image,
|
||||||
|
createInfo.width,
|
||||||
|
createInfo.height,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
eFormat,
|
||||||
|
MULTISAMPLE_TYPE_1_SAMPLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t COpenXRManager::GetHeadsetCount()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXRHeadset *COpenXRManager::GetHeadset( uint32_t i )
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
return 0;
|
||||||
|
return &m_headset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void COpenXRManager::ConnectInterface( void *pIface, const char *szName )
|
||||||
|
{
|
||||||
|
if (!V_strcmp(szName, RENDER_CONTEXT_INTERFACE_VERSION))
|
||||||
|
m_pRenderContext = (IRenderContext*)pIface;
|
||||||
|
}
|
||||||
1
external/OpenXR-SDK
vendored
Submodule
1
external/OpenXR-SDK
vendored
Submodule
Submodule external/OpenXR-SDK added at 64f2b37c8c
@@ -73,10 +73,31 @@ void CFunnyGameBridge::Init()
|
|||||||
CreateInterfaceFn fnEngineFactory = GetEngineFactory();
|
CreateInterfaceFn fnEngineFactory = GetEngineFactory();
|
||||||
g_pKotUI = (IKotUIManager*)fnEngineFactory(KOT_UI_INTEFACE_VERSION, NULL);
|
g_pKotUI = (IKotUIManager*)fnEngineFactory(KOT_UI_INTEFACE_VERSION, NULL);
|
||||||
g_pAudioManager = (IAudioManager*)fnEngineFactory(AUDIO_MANAGER_INTERFACE_VERSION, NULL);
|
g_pAudioManager = (IAudioManager*)fnEngineFactory(AUDIO_MANAGER_INTERFACE_VERSION, NULL);
|
||||||
|
g_pXRManager = (IXRManager*)fnEngineFactory(OPEN_XR_INTERFACE_VERSION, NULL);
|
||||||
|
|
||||||
g_pAudioManager->Init();
|
g_pAudioManager->Init();
|
||||||
|
|
||||||
g_pKotUI->ConnectInterface(g_pRenderContext, RENDER_CONTEXT_INTERFACE_VERSION);
|
g_pKotUI->ConnectInterface(g_pRenderContext, RENDER_CONTEXT_INTERFACE_VERSION);
|
||||||
g_pKotUI->Init();
|
g_pKotUI->Init();
|
||||||
|
|
||||||
|
g_pXRManager->ConnectInterface(g_pRenderContext, RENDER_CONTEXT_INTERFACE_VERSION);
|
||||||
|
g_pXRManager->Init();
|
||||||
|
g_pRenderContext->ConnectInterface(g_pXRManager, XR_INTERFACE_VERSION);
|
||||||
|
|
||||||
|
|
||||||
|
IXRHeadset *pHeadSet = g_pXRManager->GetHeadset(0);
|
||||||
|
for ( uint32_t i = 0; i < pHeadSet->GetSurfaceCount(); i++ )
|
||||||
|
{
|
||||||
|
XRRenderSurface_t surface = pHeadSet->GetSurface(0);
|
||||||
|
IImage *pImage = g_pRenderContext->CreateRenderTarget(surface.m_uWidth, surface.m_uHeight, IMAGE_FORMAT_RGBA8_UNORM, MULTISAMPLE_TYPE_1_SAMPLES);
|
||||||
|
pHeadSet->SetSurfaceImage(i, pImage);
|
||||||
|
IRenderCommandList *pDoSomething = g_pRenderContext->CreateCommandList();
|
||||||
|
pDoSomething->StartRecording();
|
||||||
|
pDoSomething->ClearImage(pImage, 1,0,0.5,1);
|
||||||
|
pDoSomething->EndRecording();
|
||||||
|
g_pRenderContext->SubmitCommandList(pDoSomething);
|
||||||
|
g_pRenderContext->DestroyCommandList(pDoSomething);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFunnyGameBridge::Tick( float fDelta )
|
void CFunnyGameBridge::Tick( float fDelta )
|
||||||
@@ -173,6 +194,8 @@ void CFunnyGameBridge::Frame( float fDelta )
|
|||||||
EntitySystem()->NetSendThink(pCurrentServer);
|
EntitySystem()->NetSendThink(pCurrentServer);
|
||||||
}
|
}
|
||||||
g_pWorldRenderer->Frame(fDelta);
|
g_pWorldRenderer->Frame(fDelta);
|
||||||
|
|
||||||
|
g_pXRManager->Frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFunnyGameBridge::Shutdown()
|
void CFunnyGameBridge::Shutdown()
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ IPhysicsWorld *g_pPhysicsWorld;
|
|||||||
|
|
||||||
IKotUIManager *g_pKotUI;
|
IKotUIManager *g_pKotUI;
|
||||||
IAudioManager *g_pAudioManager;
|
IAudioManager *g_pAudioManager;
|
||||||
|
IXRManager *g_pXRManager;
|
||||||
|
|
||||||
CreateInterfaceFn GetEngineFactory()
|
CreateInterfaceFn GetEngineFactory()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "ihumandevice.h"
|
#include "ihumandevice.h"
|
||||||
#include "kottui/kottui.h"
|
#include "kottui/kottui.h"
|
||||||
#include "iaudio.h"
|
#include "iaudio.h"
|
||||||
|
#include "ixr.h"
|
||||||
|
|
||||||
class CEngineVars
|
class CEngineVars
|
||||||
{
|
{
|
||||||
@@ -44,6 +45,7 @@ extern IPhysicsWorld *g_pPhysicsWorld;
|
|||||||
extern IKotUIManager *g_pKotUI;
|
extern IKotUIManager *g_pKotUI;
|
||||||
|
|
||||||
extern IAudioManager *g_pAudioManager;
|
extern IAudioManager *g_pAudioManager;
|
||||||
|
extern IXRManager *g_pXRManager;
|
||||||
|
|
||||||
#define FUNNY_SECURE_PORT 27015
|
#define FUNNY_SECURE_PORT 27015
|
||||||
#define FUNNY_QUERY_PORT 27016
|
#define FUNNY_QUERY_PORT 27016
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ void *pTier0Lib = NULL;
|
|||||||
typedef void (*EngineMainFn)(int argc, char** argv);
|
typedef void (*EngineMainFn)(int argc, char** argv);
|
||||||
EngineMainFn pEngineMain;
|
EngineMainFn pEngineMain;
|
||||||
|
|
||||||
extern "C" void FunnyMain( int argc, char **argv );
|
|
||||||
|
|
||||||
int main( int argc, char **argv ) {
|
int main( int argc, char **argv ) {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
readlink("/proc/self/exe",szLauncherPath, MAX_PATH);
|
readlink("/proc/self/exe",szLauncherPath, MAX_PATH);
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ BEGIN_VULKAN_COMMAND(ClearColor)
|
|||||||
float g;
|
float g;
|
||||||
float b;
|
float b;
|
||||||
float a;
|
float a;
|
||||||
IImage *pImage = NULL;
|
VkFrameObject_t stImage;
|
||||||
IImage **ppSwapchainImages = NULL;
|
|
||||||
END_VULKAN_COMMAND(ClearColor)
|
END_VULKAN_COMMAND(ClearColor)
|
||||||
|
|
||||||
BEGIN_VULKAN_COMMAND(Begin)
|
BEGIN_VULKAN_COMMAND(Begin)
|
||||||
|
|||||||
@@ -10,22 +10,13 @@ DECLARE_VULKAN_COMMAND(ClearColor)
|
|||||||
|
|
||||||
CVkImage *pImg;
|
CVkImage *pImg;
|
||||||
|
|
||||||
if (pImage)
|
|
||||||
pImg = (CVkImage*)pImage;
|
|
||||||
if (ppSwapchainImages)
|
|
||||||
pImg = (CVkImage*)ppSwapchainImages[iCurrentFrame];
|
|
||||||
|
|
||||||
if (pImg == NULL)
|
|
||||||
Plat_FatalErrorFunc("pImage and *ppSwapchainImages are NULL\n");
|
|
||||||
|
|
||||||
|
|
||||||
VkClearColorValue color = {.float32 = {r,g,b,a}};
|
VkClearColorValue color = {.float32 = {r,g,b,a}};
|
||||||
VkImageSubresourceRange range = {
|
VkImageSubresourceRange range = {
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
vkCmdClearColorImage(hCommandBuffer, pImg->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range);
|
vkCmdClearColorImage(hCommandBuffer, ((CVkImage*)VulkanGetObject(stImage, iCurrentFrame))->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_VULKAN_COMMAND(Begin)
|
DECLARE_VULKAN_COMMAND(Begin)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
REQUIRED_EXTENSION(VK_KHR_SWAPCHAIN)
|
REQUIRED_EXTENSION(VK_KHR_SWAPCHAIN)
|
||||||
REQUIRED_EXTENSION(VK_KHR_PIPELINE_LIBRARY)
|
REQUIRED_EXTENSION(VK_KHR_PIPELINE_LIBRARY)
|
||||||
REQUIRED_EXTENSION(VK_EXT_GRAPHICS_PIPELINE_LIBRARY)
|
REQUIRED_EXTENSION(VK_EXT_GRAPHICS_PIPELINE_LIBRARY)
|
||||||
|
REQUIRED_EXTENSION(VK_KHR_EXTERNAL_FENCE_CAPABILITIES)
|
||||||
OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE)
|
OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE)
|
||||||
OPTIONAL_EXTENSION(VK_KHR_ACCELERATION_STRUCTURE)
|
OPTIONAL_EXTENSION(VK_KHR_ACCELERATION_STRUCTURE)
|
||||||
OPTIONAL_EXTENSION(VK_KHR_DEFERRED_HOST_OPERATIONS)
|
OPTIONAL_EXTENSION(VK_KHR_DEFERRED_HOST_OPERATIONS)
|
||||||
|
|||||||
@@ -198,6 +198,57 @@ void CVkRenderCommandList::DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CVkRenderCommandList::CopyImageToImage( IImage *pSrc, IImage *pDst )
|
||||||
|
{
|
||||||
|
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
|
||||||
|
|
||||||
|
}
|
||||||
|
void CVkRenderCommandList::BlitImageToImage( IImage *pSrc, ImageSector_t src, IImage *pDst, ImageSector_t dst )
|
||||||
|
{
|
||||||
|
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
|
||||||
|
CVkBlitCommand *pCmd = CREATE_COMMAND(m_pCommandBufferManager, Blit);
|
||||||
|
pCmd->stInputImage.m_eObjectType = FRAME_OBJECT_TYPE_SINGLE;
|
||||||
|
pCmd->stInputImage.m_pSingle = pSrc;
|
||||||
|
pCmd->stOutputImage.m_eObjectType = FRAME_OBJECT_TYPE_SINGLE;
|
||||||
|
pCmd->stOutputImage.m_pSingle = pDst;
|
||||||
|
pCmd->AddDependency(pSrc, DEPENDENCY_MODE_BLIT_IMAGE_SOURCE);
|
||||||
|
pCmd->AddDependency(pDst, DEPENDENCY_MODE_BLIT_IMAGE_DESTINATION);
|
||||||
|
pCmd->iSrcMin[0] = src.m_iX;
|
||||||
|
pCmd->iSrcMin[1] = src.m_iY;
|
||||||
|
pCmd->iSrcMin[2] = 0;
|
||||||
|
pCmd->iDstMin[0] = dst.m_iX;
|
||||||
|
pCmd->iDstMin[1] = dst.m_iY;
|
||||||
|
pCmd->iDstMin[2] = 0;
|
||||||
|
pCmd->iSrcMax[0] = src.m_iWidth;
|
||||||
|
pCmd->iSrcMax[1] = src.m_iHeight;
|
||||||
|
pCmd->iSrcMax[2] = 1;
|
||||||
|
pCmd->iDstMax[0] = dst.m_iWidth;
|
||||||
|
pCmd->iDstMax[1] = dst.m_iHeight;
|
||||||
|
pCmd->iDstMax[2] = 1;
|
||||||
|
m_pPostRaster->AddCommand(pCmd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVkRenderCommandList::ClearImage( IImage *pImage, float fR, float fG, float fB, float fA )
|
||||||
|
{
|
||||||
|
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
|
||||||
|
CVkClearColorCommand *pCmd = CREATE_COMMAND(m_pCommandBufferManager, ClearColor);
|
||||||
|
pCmd->AddDependency(pImage, DEPENDENCY_MODE_COLOR_CLEAR_DESTINATION);
|
||||||
|
pCmd->r = fR;
|
||||||
|
pCmd->g = fG;
|
||||||
|
pCmd->b = fB;
|
||||||
|
pCmd->a = fA;
|
||||||
|
pCmd->stImage.m_eObjectType = FRAME_OBJECT_TYPE_SINGLE;
|
||||||
|
pCmd->stImage.m_pSingle = pImage;
|
||||||
|
m_pPostRaster->AddCommand(pCmd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVkRenderCommandList::ClearDepth( IImage *pImage, float fVal )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void CVkRenderCommandList::ResolveImage( IImage *pOriginal, IImage *pResolved )
|
void CVkRenderCommandList::ResolveImage( IImage *pOriginal, IImage *pResolved )
|
||||||
{
|
{
|
||||||
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
|
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
|
||||||
@@ -251,8 +302,11 @@ void CVkRenderCommandList::SwitchRenderingStage( EVulkanRenderingStage eStage )
|
|||||||
};
|
};
|
||||||
if (eStage == RENDERING_STAGE_POST_RASTER)
|
if (eStage == RENDERING_STAGE_POST_RASTER)
|
||||||
{
|
{
|
||||||
m_pPostRaster = m_pCommandBufferManager->CreateCommandBuffer();
|
if (m_eCurrentStage != RENDERING_STAGE_POST_RASTER)
|
||||||
m_pPostRaster->Reset();
|
{
|
||||||
|
m_pPostRaster = m_pCommandBufferManager->CreateCommandBuffer();
|
||||||
|
m_pPostRaster->Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -262,6 +316,7 @@ void CVkRenderCommandList::SwitchRenderingStage( EVulkanRenderingStage eStage )
|
|||||||
m_pCommandBuffers.AppendTail(m_pPostRaster);
|
m_pCommandBuffers.AppendTail(m_pPostRaster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_eCurrentStage = eStage;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanRenderOutput_t *CVkRenderCommandList::FindOrCreateRenderOutput( uint32_t uIndex )
|
VulkanRenderOutput_t *CVkRenderCommandList::FindOrCreateRenderOutput( uint32_t uIndex )
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "materialsystem/igamewindow.h"
|
#include "materialsystem/igamewindow.h"
|
||||||
#include "libraries.h"
|
#include "libraries.h"
|
||||||
#include "stb/stb_image.h"
|
#include "stb/stb_image.h"
|
||||||
|
#include "ixr.h"
|
||||||
|
|
||||||
|
|
||||||
#define REQUIRED_EXTENSION(ext) ext##_EXTENSION_NAME,
|
#define REQUIRED_EXTENSION(ext) ext##_EXTENSION_NAME,
|
||||||
@@ -137,6 +138,8 @@ VkFormat CVkImage::GetImageFormat( enum EImageFormat eImageFormat )
|
|||||||
return VK_FORMAT_R8G8B8A8_UINT;
|
return VK_FORMAT_R8G8B8A8_UINT;
|
||||||
case IMAGE_FORMAT_RGBA8_SINT:
|
case IMAGE_FORMAT_RGBA8_SINT:
|
||||||
return VK_FORMAT_R8G8B8A8_SINT;
|
return VK_FORMAT_R8G8B8A8_SINT;
|
||||||
|
case IMAGE_FORMAT_RGBA8_SRGB:
|
||||||
|
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
|
||||||
case IMAGE_FORMAT_RGBA16_UINT:
|
case IMAGE_FORMAT_RGBA16_UINT:
|
||||||
return VK_FORMAT_R16G16B16A16_UINT;
|
return VK_FORMAT_R16G16B16A16_UINT;
|
||||||
@@ -451,6 +454,7 @@ public:
|
|||||||
virtual void Init() override;
|
virtual void Init() override;
|
||||||
virtual void Frame( float fDeltaTime ) override;
|
virtual void Frame( float fDeltaTime ) override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
|
virtual void ConnectInterface( void *pIface, const char *szName ) override;
|
||||||
|
|
||||||
virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override;
|
virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override;
|
||||||
virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override;
|
virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override;
|
||||||
@@ -478,8 +482,6 @@ public:
|
|||||||
virtual void DestroyCommandList( IRenderCommandList *pCommandList ) override;
|
virtual void DestroyCommandList( IRenderCommandList *pCommandList ) override;
|
||||||
virtual void SubmitCommandList(IRenderCommandList *pList) override;
|
virtual void SubmitCommandList(IRenderCommandList *pList) override;
|
||||||
|
|
||||||
virtual void SetMainWindowManager( IGameWindowManager *pWindowManager ) override;
|
|
||||||
|
|
||||||
virtual void RenderGameWindow( IGameWindow *pWindow ) override;
|
virtual void RenderGameWindow( IGameWindow *pWindow ) override;
|
||||||
virtual void RegisterGameWindow( IGameWindow *pWindow ) override;
|
virtual void RegisterGameWindow( IGameWindow *pWindow ) override;
|
||||||
virtual void UnregisterGameWindow( IGameWindow *pWindow ) override;
|
virtual void UnregisterGameWindow( IGameWindow *pWindow ) override;
|
||||||
@@ -488,6 +490,11 @@ public:
|
|||||||
virtual void DestroyTextureArray() override;
|
virtual void DestroyTextureArray() override;
|
||||||
|
|
||||||
virtual ISampler *GetDefaultSampler() override;
|
virtual ISampler *GetDefaultSampler() override;
|
||||||
|
|
||||||
|
virtual void *GetVulkanInstance() override;
|
||||||
|
virtual void *GetVulkanPhysicalDevice() override;
|
||||||
|
virtual void *GetVulkanDevice() override;
|
||||||
|
virtual IImage *CreateImageFromVkImage( void *pVkImage, uint32_t x, uint32_t y, uint64_t optimalLayout, EImageFormat eFormat, EMultisampleType eMultisampleType ) override;
|
||||||
private:
|
private:
|
||||||
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
|
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
|
||||||
CUtlVector<const char *> GetDeviceExtensions();
|
CUtlVector<const char *> GetDeviceExtensions();
|
||||||
@@ -497,7 +504,8 @@ private:
|
|||||||
VulkanWindow_t CreateSwapchain( IGameWindow *pWindow );
|
VulkanWindow_t CreateSwapchain( IGameWindow *pWindow );
|
||||||
void DestroySwapchain( uint32_t uIndex );
|
void DestroySwapchain( uint32_t uIndex );
|
||||||
|
|
||||||
IGameWindowManager *m_pWindowManager;
|
IGameWindowManager *m_pWindowManager = NULL;
|
||||||
|
IXRManager *m_pXRManager = NULL;
|
||||||
IVkCommandBufferManager *m_pCommandBufferManager;
|
IVkCommandBufferManager *m_pCommandBufferManager;
|
||||||
IVkCommandBufferManager *m_pAssetsCommandBufferManager;
|
IVkCommandBufferManager *m_pAssetsCommandBufferManager;
|
||||||
|
|
||||||
@@ -515,6 +523,14 @@ private:
|
|||||||
EXPOSE_INTERFACE(CVkRenderContext, IRenderContext, RENDER_CONTEXT_INTERFACE_VERSION);
|
EXPOSE_INTERFACE(CVkRenderContext, IRenderContext, RENDER_CONTEXT_INTERFACE_VERSION);
|
||||||
|
|
||||||
|
|
||||||
|
void CVkRenderContext::ConnectInterface( void *pIface, const char *szName )
|
||||||
|
{
|
||||||
|
if (!V_strcmp(szName, GAME_WINDOW_MANAGER_INTERFACE_VERSION))
|
||||||
|
m_pWindowManager = (IGameWindowManager*)pIface;
|
||||||
|
if (!V_strcmp(szName, XR_INTERFACE_VERSION))
|
||||||
|
m_pXRManager = (IXRManager*)pIface;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Creates vertex buffer. Wrapper over CreateBuffer
|
// Creates vertex buffer. Wrapper over CreateBuffer
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -660,11 +676,6 @@ void CVkRenderContext::RenderGameWindow( IGameWindow *pWindow )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVkRenderContext::SetMainWindowManager( IGameWindowManager *pWindowManager )
|
|
||||||
{
|
|
||||||
m_pWindowManager = pWindowManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVkRenderContext::RegisterGameWindow( IGameWindow *pWindow )
|
void CVkRenderContext::RegisterGameWindow( IGameWindow *pWindow )
|
||||||
{
|
{
|
||||||
VulkanWindow_t window = CreateSwapchain(pWindow);
|
VulkanWindow_t window = CreateSwapchain(pWindow);
|
||||||
@@ -696,6 +707,35 @@ ISampler *CVkRenderContext::GetDefaultSampler()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *CVkRenderContext::GetVulkanInstance()
|
||||||
|
{
|
||||||
|
return s_vkInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CVkRenderContext::GetVulkanPhysicalDevice()
|
||||||
|
{
|
||||||
|
return s_vkPhysicalDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CVkRenderContext::GetVulkanDevice()
|
||||||
|
{
|
||||||
|
return s_vkDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
IImage *CVkRenderContext::CreateImageFromVkImage( void *pVkImage, uint32_t x, uint32_t y, uint64_t optimalLayout, EImageFormat eFormat, EMultisampleType eMultisampleType )
|
||||||
|
{
|
||||||
|
CVkImage *pImage;
|
||||||
|
pImage = new CVkImage;
|
||||||
|
pImage->m_image = (VkImage)pVkImage;
|
||||||
|
pImage->m_eImageType = IMAGE_TYPE_2D;
|
||||||
|
pImage->m_eMultisampleType = eMultisampleType;
|
||||||
|
pImage->m_eFormat = eFormat;
|
||||||
|
pImage->m_nHeight = x;
|
||||||
|
pImage->m_nWidth = y;
|
||||||
|
pImage->m_ePreferredLayout = (VkImageLayout)optimalLayout;
|
||||||
|
pImage->CreateImageView();
|
||||||
|
return pImage;
|
||||||
|
}
|
||||||
|
|
||||||
VkPipelineLayout g_pLibraryEmptyLayout;
|
VkPipelineLayout g_pLibraryEmptyLayout;
|
||||||
static IVkCommandBuffer *s_pPresentCommandBuffer;
|
static IVkCommandBuffer *s_pPresentCommandBuffer;
|
||||||
@@ -746,6 +786,7 @@ void CVkRenderContext::Init()
|
|||||||
|
|
||||||
stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo;
|
stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo;
|
||||||
|
enabledInstanceExtensions.AppendTail(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||||
stInstanceCreateInfo.enabledExtensionCount = enabledInstanceExtensions.GetSize();
|
stInstanceCreateInfo.enabledExtensionCount = enabledInstanceExtensions.GetSize();
|
||||||
stInstanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions.GetData();
|
stInstanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions.GetData();
|
||||||
|
|
||||||
@@ -814,6 +855,7 @@ void CVkRenderContext::Init()
|
|||||||
vk11Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
|
vk11Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
|
||||||
vk11Features.pNext = &vk12Features;
|
vk11Features.pNext = &vk12Features;
|
||||||
vk11Features.shaderDrawParameters = VK_TRUE;
|
vk11Features.shaderDrawParameters = VK_TRUE;
|
||||||
|
vk11Features.multiview = VK_TRUE;
|
||||||
|
|
||||||
|
|
||||||
stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
@@ -915,6 +957,7 @@ void CVkRenderContext::Frame( float fDeltaTime )
|
|||||||
uImageIndexes.AppendTail(s.m_uCurrentFrame);
|
uImageIndexes.AppendTail(s.m_uCurrentFrame);
|
||||||
}
|
}
|
||||||
uSwapchainImageIndexes.Resize(m_renderWindows.GetSize());
|
uSwapchainImageIndexes.Resize(m_renderWindows.GetSize());
|
||||||
|
|
||||||
|
|
||||||
vkWaitForFences(s_vkDevice, fences.GetSize(), fences.GetData(), VK_TRUE, UINT64_MAX);
|
vkWaitForFences(s_vkDevice, fences.GetSize(), fences.GetData(), VK_TRUE, UINT64_MAX);
|
||||||
vkResetFences(s_vkDevice, fences.GetSize(), fences.GetData());
|
vkResetFences(s_vkDevice, fences.GetSize(), fences.GetData());
|
||||||
@@ -925,6 +968,9 @@ void CVkRenderContext::Frame( float fDeltaTime )
|
|||||||
VkResult r = vkAcquireNextImageKHR(s_vkDevice, s.m_swapchain, UINT64_MAX, s.m_imageAvailable[s.m_uCurrentFrame], NULL, &uSwapchainImageIndexes[i]);
|
VkResult r = vkAcquireNextImageKHR(s_vkDevice, s.m_swapchain, UINT64_MAX, s.m_imageAvailable[s.m_uCurrentFrame], NULL, &uSwapchainImageIndexes[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_pXRManager)
|
||||||
|
m_pXRManager->PreRender();
|
||||||
|
|
||||||
|
|
||||||
s_pPresentCommandBuffer = m_pCommandBufferManager->CreateCommandBuffer();
|
s_pPresentCommandBuffer = m_pCommandBufferManager->CreateCommandBuffer();
|
||||||
@@ -965,6 +1011,9 @@ void CVkRenderContext::Frame( float fDeltaTime )
|
|||||||
s_pPresentCommandBuffer->Render();
|
s_pPresentCommandBuffer->Render();
|
||||||
s_pPresentCommandBuffer->Submit(0);
|
s_pPresentCommandBuffer->Submit(0);
|
||||||
|
|
||||||
|
if (m_pXRManager)
|
||||||
|
m_pXRManager->CopySwapchain();
|
||||||
|
|
||||||
|
|
||||||
VkPipelineStageFlags uPipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
VkPipelineStageFlags uPipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
VkSubmitInfo stSubmitInfo = {};
|
VkSubmitInfo stSubmitInfo = {};
|
||||||
@@ -992,6 +1041,8 @@ void CVkRenderContext::Frame( float fDeltaTime )
|
|||||||
|
|
||||||
vkQueuePresentKHR(s_vkPresentQueue, &stPresentInfo);
|
vkQueuePresentKHR(s_vkPresentQueue, &stPresentInfo);
|
||||||
vkDeviceWaitIdle(s_vkDevice);
|
vkDeviceWaitIdle(s_vkDevice);
|
||||||
|
if (m_pXRManager)
|
||||||
|
m_pXRManager->PostRender();
|
||||||
|
|
||||||
for ( auto &s: m_renderWindows )
|
for ( auto &s: m_renderWindows )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -491,6 +491,11 @@ public:
|
|||||||
|
|
||||||
virtual void Barrier( IRenderingObject *pObject, bool bIsRead, bool bIsWrite ) override;
|
virtual void Barrier( IRenderingObject *pObject, bool bIsRead, bool bIsWrite ) override;
|
||||||
|
|
||||||
|
virtual void CopyImageToImage( IImage *pSrc, IImage *pDst ) override;
|
||||||
|
virtual void BlitImageToImage( IImage *pSrc, ImageSector_t src, IImage *pDst, ImageSector_t dst ) override;
|
||||||
|
virtual void ClearImage( IImage *pImage, float fR, float fG, float fB, float fA ) override;
|
||||||
|
virtual void ClearDepth( IImage *pImage, float fVal ) override;
|
||||||
|
|
||||||
void Submit();
|
void Submit();
|
||||||
|
|
||||||
IVkCommandBufferManager *m_pCommandBufferManager;
|
IVkCommandBufferManager *m_pCommandBufferManager;
|
||||||
@@ -514,6 +519,8 @@ private:
|
|||||||
CUtlVector<IVkCommandBuffer*> m_pCommandBuffers = {};
|
CUtlVector<IVkCommandBuffer*> m_pCommandBuffers = {};
|
||||||
CUtlVector<IVkCommandBuffer*> m_pScheduledDestroyPostRaster = {};
|
CUtlVector<IVkCommandBuffer*> m_pScheduledDestroyPostRaster = {};
|
||||||
CUtlVector<VkRenderBarrier_t> m_barriers = {};
|
CUtlVector<VkRenderBarrier_t> m_barriers = {};
|
||||||
|
|
||||||
|
EVulkanRenderingStage m_eCurrentStage = RENDERING_STAGE_SETUP_RASTER;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
37
public/ixr.h
37
public/ixr.h
@@ -3,12 +3,47 @@
|
|||||||
|
|
||||||
#include "tier1/interface.h"
|
#include "tier1/interface.h"
|
||||||
#include "tier2/iappsystem.h"
|
#include "tier2/iappsystem.h"
|
||||||
|
#include "materialsystem/imaterialsystem.h"
|
||||||
#include "trig.h"
|
#include "trig.h"
|
||||||
|
|
||||||
abstract_class IXrManager: public IAppSystem
|
struct XRRenderSurface_t
|
||||||
|
{
|
||||||
|
uint32_t m_uWidth;
|
||||||
|
uint32_t m_uHeight;
|
||||||
|
Vector m_vPosition;
|
||||||
|
Quat m_vRotation;
|
||||||
|
float m_fFov;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IXRHeadset
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual uint32_t GetSurfaceCount() = 0;
|
||||||
|
virtual XRRenderSurface_t GetSurface( uint32_t i ) = 0;
|
||||||
|
virtual void SetSurfaceImage( uint32_t i, IImage *pImage ) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
abstract_class IXRController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IXRManager: public IAppSystem2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Frame() = 0;
|
||||||
|
virtual void PreRender() = 0;
|
||||||
|
virtual void PostRender() = 0;
|
||||||
|
virtual void CopySwapchain() = 0;
|
||||||
|
virtual uint32_t GetHeadsetCount() = 0;
|
||||||
|
virtual IXRHeadset *GetHeadset( uint32_t i ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XR_INTERFACE_VERSION "XR001"
|
||||||
|
#define OPEN_XR_INTERFACE_VERSION "Open" XR_INTERFACE_VERSION
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ enum EImageFormat
|
|||||||
|
|
||||||
IMAGE_FORMAT_RGBA8_UINT,
|
IMAGE_FORMAT_RGBA8_UINT,
|
||||||
IMAGE_FORMAT_RGBA8_SINT,
|
IMAGE_FORMAT_RGBA8_SINT,
|
||||||
|
IMAGE_FORMAT_RGBA8_SRGB,
|
||||||
|
|
||||||
IMAGE_FORMAT_RGBA16_UINT,
|
IMAGE_FORMAT_RGBA16_UINT,
|
||||||
IMAGE_FORMAT_RGBA16_SINT,
|
IMAGE_FORMAT_RGBA16_SINT,
|
||||||
@@ -260,6 +261,14 @@ public:
|
|||||||
virtual void PSSetSampler( uint32_t uRegister, ISampler *pImage ) = 0;
|
virtual void PSSetSampler( uint32_t uRegister, ISampler *pImage ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImageSector_t
|
||||||
|
{
|
||||||
|
int32_t m_iX;
|
||||||
|
int32_t m_iY;
|
||||||
|
int32_t m_iWidth;
|
||||||
|
int32_t m_iHeight;
|
||||||
|
};
|
||||||
|
|
||||||
abstract_class IRenderCommandList
|
abstract_class IRenderCommandList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -289,6 +298,11 @@ public:
|
|||||||
virtual void EndRecording() = 0;
|
virtual void EndRecording() = 0;
|
||||||
|
|
||||||
virtual void Barrier( IRenderingObject *pObject, bool bIsRead, bool bIsWrite ) = 0;
|
virtual void Barrier( IRenderingObject *pObject, bool bIsRead, bool bIsWrite ) = 0;
|
||||||
|
|
||||||
|
virtual void CopyImageToImage( IImage *pSrc, IImage *pDst ) = 0;
|
||||||
|
virtual void BlitImageToImage( IImage *pSrc, ImageSector_t src, IImage *pDst, ImageSector_t dst ) = 0;
|
||||||
|
virtual void ClearImage( IImage *pImage, float fR, float fG, float fB, float fA ) = 0;
|
||||||
|
virtual void ClearDepth( IImage *pImage, float fVal ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -296,7 +310,7 @@ public:
|
|||||||
//
|
//
|
||||||
// Responsible for the object handling
|
// Responsible for the object handling
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
abstract_class IRenderContext: public IAppSystem
|
abstract_class IRenderContext: public IAppSystem2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Frame( float fTime ) = 0;
|
virtual void Frame( float fTime ) = 0;
|
||||||
@@ -324,8 +338,6 @@ public:
|
|||||||
virtual void DestroyCommandList( IRenderCommandList *pCommandList ) = 0;
|
virtual void DestroyCommandList( IRenderCommandList *pCommandList ) = 0;
|
||||||
virtual void SubmitCommandList(IRenderCommandList *pList) = 0;
|
virtual void SubmitCommandList(IRenderCommandList *pList) = 0;
|
||||||
|
|
||||||
virtual void SetMainWindowManager( IGameWindowManager *pWindowManager ) = 0;
|
|
||||||
|
|
||||||
virtual void RenderGameWindow( IGameWindow *pWindow ) = 0;
|
virtual void RenderGameWindow( IGameWindow *pWindow ) = 0;
|
||||||
virtual void RegisterGameWindow( IGameWindow *pWindow ) = 0;
|
virtual void RegisterGameWindow( IGameWindow *pWindow ) = 0;
|
||||||
virtual void UnregisterGameWindow( IGameWindow *pWindow ) = 0;
|
virtual void UnregisterGameWindow( IGameWindow *pWindow ) = 0;
|
||||||
@@ -334,6 +346,11 @@ public:
|
|||||||
virtual void DestroyTextureArray() = 0;
|
virtual void DestroyTextureArray() = 0;
|
||||||
|
|
||||||
virtual ISampler *GetDefaultSampler() = 0;
|
virtual ISampler *GetDefaultSampler() = 0;
|
||||||
|
|
||||||
|
virtual void *GetVulkanInstance() = 0;
|
||||||
|
virtual void *GetVulkanPhysicalDevice() = 0;
|
||||||
|
virtual void *GetVulkanDevice() = 0;
|
||||||
|
virtual IImage *CreateImageFromVkImage( void *pVkImage, uint32_t x, uint32_t y, uint64_t optimalLayout, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RENDER_CONTEXT_INTERFACE_VERSION "RenderContext001"
|
#define RENDER_CONTEXT_INTERFACE_VERSION "RenderContext001"
|
||||||
|
|||||||
Reference in New Issue
Block a user