DirectX到OpenGL热插拔,不显示在Win32窗口

时间:2016-05-31 14:30:59

标签: winapi opengl directx hwnd hotswap

在我的引擎开发期间,我正在尝试实现一个功能,它可以在OpenGL和DirectX之间进行热交换。目前我正在Win32平台上测试,并遇到了以下问题:

我实现了渲染器(OpenGL 3.0和Direct3D11),两者都很好。交换机制如下:

销毁当前渲染上下文,并构建新的上下文。例如:释放所有DirectX对象,然后通过WGL创建OpenGL上下文。我正在尝试使用一个窗口(HWND)来实现它。

从OpenGL 3.0交换到DirectX11可以正常工作。 (在销毁OpenGL之后,DirectX渲染得很好)

销毁OpenGL,然后再次重新创建OpenGL,有效。与DirectX相同。

当我尝试从DirectX切换到OpenGL时,窗口将停止显示新绘制的内容,只显示最后绘制的DirectX帧。

构建OpenGL上下文我正在使用WGL。窗口的类是使用CS_OWNDC样式创建的。我正在使用SwapBuffers翻转窗口缓冲区。在设置上下文之前,我使用SetPixelFormat与先前从ChoosePixelFormat返回的值。创建的上下文是3.0版,通过wglCreateContextAttribsARB确保。

其他信息:

释放所有DirectX引用,通过调用ReportLiveDeviceObjects并检查ID3D11Device1::Release(0)的返回值来检查。调用了ID3D11DeviceContext1::ClearStateFlush来确保对象被破坏。

没有一个OpenGL方法通过glGetError报告错误,每次调用后都会检查此错误。对于所有操作系统和WGL调用都是一样的。

OpenGL渲染调用正在按预期执行,例如:

  1. 使用150 fps的OpenGL渲染
  2. 交换到DirectX,以60 fps(VSYNC)渲染
  3. 交换回OpenGL,再次使用150 fps(不是更多)
  4. 进行渲染

    还有其他场景,OpenGL以超过150 fps的速度渲染,因此渲染调用正在正确执行。

    我的猜测是缓冲区的翻转无法以某种方式起作用,但无论如何SwapBuffers都会返回TRUE

    我尝试在使用DirectX之前和之后使用SaveDCRestoreDC,这导致了现在的解决方案。

    使用wglSwapLayerBuffers代替SwapBuffers不会发生任何变化。

    我可以以某种方式将HWND或HDC恢复到原始状态,或者您是否知道为什么会发生这种情况?

1 个答案:

答案 0 :(得分:1)

猜猜我很快就发布了我的问题,但是,这就是我解决它的方法。

我挖掘了DirectX的文档,对于函数CreateSwapChainForHwnd,我发现了以下内容:

  

因为您一次只能将一个翻转演示模型交换链与HWND关联,所以如果您尝试销毁翻转演示模型交换链并将其替换为对象,则推迟销毁对象的Microsoft Direct3D 11策略可能会导致问题另一个交换链。

我在交换链描述符中使用DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,这可能意味着DirectX为窗口设置了一个翻转交换链,但是当我尝试将它与OpenGL一起使用时,它将无法以某种方式交换缓冲区

解决方法是不使用FLIP模式创建交换链:

DXGI_SWAP_CHAIN_DESC1 scd;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;          
scd.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;

您必须将Scaling设置为DXGI_SCALING_NONE之外的其他内容,否则创建将失败。

有趣的是,DirectX仍然没有正确破坏窗口上的翻转模型,尽管我做了文档中提出的所有内容(ClearStateFlush调用)。

CreateSwapChainForHwnd see Remarks

编辑:过了一段时间后我发现了this个问题。如果有人仍然有一些想法,如何再次使用GDI而不是DWM后备缓冲器,我们非常感激。