xrEndFrame 上奇怪的 OpenXR 行为

Strange OpenXR Behaviour on xrEndFrame

首先:上下文是使用 HP Reverb G2、WMR 运行时、DX12 的 VR。

在使用 OpenXR 时,我们在开发人员机器上看到了一些无法解释的行为。看起来 OpenXR 运行时正在根据首选 GPU 的机器设置改变它的呈现方式。

更具体地说,我们注意到根据首选 GPU 的机器设置,我们看到在调用 XrEndFrame 时使用了不同的方法。这是一个大问题,因为不同的方法会导致空白屏幕被绘制到我们当前的 renderTarget!

不同之处在于,当首选设备是 Nvidia GPU 时,xrEndFrame 在 PIX 中看起来像这样(在独立于我们的主渲染的图形队列中):

Index   Global ID   Name    EOP to EOP Duration (ns)    Execution Start Time (ns)
2   8063    Signal(pFence:obj#20, Value:62)     
3   8064    Wait(pFence:obj#36, Value:31)       
5   8065    CopyTextureRegion(pDst:{pResource:obj#4083, Type:D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, SubresourceIndex:0}, DstX:0, DstY:0, DstZ:0, pSrc:{pResource:obj#4084, Type:D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, SubresourceIndex:0}, pSrcBox:{left:0, top:0, front:0, right:2088, bottom:2036, back:1})      
6   8066    CopyTextureRegion(pDst:{pResource:obj#4083, Type:D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, SubresourceIndex:1}, DstX:0, DstY:0, DstZ:0, pSrc:{pResource:obj#4085, Type:D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, SubresourceIndex:0}, pSrcBox:{left:0, top:0, front:0, right:2088, bottom:2036, back:1})      
8   8067    Signal(pFence:obj#20, Value:63)     
9   8068    Signal(pFence:obj#21, Value:31)     

如果不是,(即可能以某种方式搭载英特尔?)它看起来像这样:

Index   Global ID   Name    EOP to EOP Duration (ns)    Execution Start Time (ns)
0   8064    Wait(pFence:obj#45, Value:21)       
2   8065    ClearRenderTargetView(RenderTargetView:res#4008, ColorRGBA:{Element:0, Element:0, Element:0, Element:0}, NumRects:0, pRects:nullptr)        
15  8066    DrawIndexedInstanced(IndexCountPerInstance:4, InstanceCount:2, StartIndexLocation:0, BaseVertexLocation:0, StartInstanceLocation:0)     
17  8067    Signal(pFence:obj#22, Value:23)     
18  8068    Signal(pFence:obj#23, Value:21)     

后者正在清除当前的 renderTargetView 并在顶部绘制一个四边形,这是耳机显示器的尺寸。

然而-我们检查了渲染代码,它肯定没有选择英特尔图形设备。但是,如果我们在 nvidia 控制面板中将 'preferred graphics processor' 设置为 nvidia gpu,第二种行为就会消失。

我们还可以看到上述行为是调用 XrEndFrame 的结果,并且我们的渲染代码在其他方面是相同的。

关于运行时的哪一部分可能正在查看或受此设置影响的任何线索?

不幸的是(幸运的是?)我们发现我们需要处理渲染代码才能交换运行时说 SteamVR,所以现在我们不能交换运行时。

显然我们有一个解决方法,就是设置首选设备。但是了解 how/why 这个问题的发生会很棒。

所以这最终被追踪到是我们的错误。 在我们的例子中,我们使用 xrGetD3D12GraphicsRequirementsKHR 来获得 openxr 的最低图形要求。

这在结构 XrGraphicsRequirementsD3D12KHR 中有一个 adapterLuid 标识符,我们本应将其用于 select 图形 API 中的 GPU,但没有。