Render through public Qt API: OpenGL and Vulkan backends, --graphics-api
Replace the QRhi rendering in OverlayController (private Qt API) with the render backends of the vrdashboard template (src/render/), which use public Qt API only (QQuickRenderTarget::fromOpenGLTexture / fromVulkanImage). The binary then runs on another Qt 6 patch release, e.g. the Steam Frame's system Qt. The Vulkan backend also does what SteamVR requires and the QRhi path lacked: the required instance/device extensions and the HMD's GPU (via openvr_init::renderInterop()), VK_FORMAT_R8G8B8A8_UNORM, and the transition to TRANSFER_SRC_OPTIMAL after each frame. - New option --graphics-api opengl|vulkan (default opengl, no fallback). - Shutdown() calls VR_Shutdown before the render target and Qt's device go (crash on the Steam Frame with Vulkan otherwise); it runs only once. - Mouse y is flipped on every platform: SteamVR reports it in GL convention. - Render delay 5 -> 16 ms (about 60 fps). - GuiPrivate is no longer needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
423ea57db7
commit
4826686a4d
@@ -6,6 +6,7 @@
|
||||
#include <QtLogging>
|
||||
#include <QtDebug>
|
||||
#include "../openvr/ivrinput_manifest.h"
|
||||
#include <QByteArray>
|
||||
|
||||
namespace openvr_init
|
||||
{
|
||||
@@ -136,4 +137,74 @@ void initializeOpenVR( const OpenVrInitializationType initType, int count )
|
||||
}
|
||||
}
|
||||
|
||||
// Calls an OpenVR "Get...ExtensionsRequired" function and splits its
|
||||
// space-separated result. `query( buffer, size )` returns the size needed,
|
||||
// including the terminating zero.
|
||||
template <typename Query>
|
||||
static QByteArrayList queryExtensionList( Query query )
|
||||
{
|
||||
const uint32_t size = query( nullptr, 0 );
|
||||
if ( size == 0 )
|
||||
{
|
||||
return {};
|
||||
}
|
||||
QByteArray buffer( static_cast<int>( size ), '\0' );
|
||||
query( buffer.data(), size );
|
||||
QByteArrayList result;
|
||||
for ( const QByteArray& ext :
|
||||
buffer.left( buffer.indexOf( '\0' ) ).split( ' ' ) )
|
||||
{
|
||||
if ( !ext.isEmpty() )
|
||||
{
|
||||
result.append( ext );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Same as the template's VrRuntime::renderInterop(). The functions are called
|
||||
// by the Vulkan backend while it creates its instance and device.
|
||||
RenderInterop renderInterop()
|
||||
{
|
||||
RenderInterop interop;
|
||||
interop.vulkanInstanceExtensions = []
|
||||
{
|
||||
vr::IVRCompositor* compositor = vr::VRCompositor();
|
||||
if ( !compositor )
|
||||
{
|
||||
qWarning() << "IVRCompositor unavailable: cannot query required "
|
||||
"Vulkan instance extensions";
|
||||
return QByteArrayList();
|
||||
}
|
||||
return queryExtensionList(
|
||||
[&]( char* buffer, uint32_t size )
|
||||
{
|
||||
return compositor->GetVulkanInstanceExtensionsRequired( buffer,
|
||||
size );
|
||||
} );
|
||||
};
|
||||
interop.vulkanDeviceExtensions = []( VkPhysicalDevice_T* device )
|
||||
{
|
||||
vr::IVRCompositor* compositor = vr::VRCompositor();
|
||||
if ( !compositor )
|
||||
{
|
||||
return QByteArrayList();
|
||||
}
|
||||
return queryExtensionList(
|
||||
[&]( char* buffer, uint32_t size )
|
||||
{
|
||||
return compositor->GetVulkanDeviceExtensionsRequired(
|
||||
device, buffer, size );
|
||||
} );
|
||||
};
|
||||
interop.vulkanOutputDevice = []( VkInstance_T* instance )
|
||||
{
|
||||
uint64_t device = 0;
|
||||
vr::VRSystem()->GetOutputDevice(
|
||||
&device, vr::TextureType_Vulkan, instance );
|
||||
return reinterpret_cast<VkPhysicalDevice_T*>( device );
|
||||
};
|
||||
return interop;
|
||||
}
|
||||
|
||||
} // namespace openvr_init
|
||||
|
||||
Reference in New Issue
Block a user