Горячая замена DirectX на OpenGL, не отображается в окне Win32

Во время разработки своего движка я пытаюсь реализовать функцию, которая позволяет выполнять «горячую» замену между OpenGL и DirectX. В настоящее время я тестирую платформу Win32 и столкнулся со следующей проблемой:

Я реализовал оба средства рендеринга (OpenGL 3.0 и Direct3D11), оба работают нормально в одиночку. Механизм подкачки следующий:

Уничтожьте текущий контекст рендеринга и создайте новый. Например: освободите все объекты DirectX, а затем создайте контекст OpenGL через WGL. Я пытаюсь реализовать это, используя только одно окно (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::ClearState и Flush были вызваны для обеспечения разрушения объекта.

Ни один из методов OpenGL не сообщает об ошибке через glGetError, это проверяется после каждого вызова. Это то же самое для всех ОС и вызовов WGL.

Вызовы рендеринга OpenGL выполняются должным образом, например:

  1. Рендеринг OpenGL со скоростью 150 кадров в секунду
  2. Переход на DirectX, рендеринг со скоростью 60 кадров в секунду (VSYNC)
  3. Вернитесь к OpenGL, снова рендеринг со скоростью 150 кадров в секунду (не более)

Существуют и другие сценарии, в которых OpenGL выполняет рендеринг со скоростью более 150 кадров в секунду, поэтому вызовы рендеринга выполняются правильно.

Я предполагаю, что переключение буферов как-то не работает, однако SwapBuffers все равно возвращает TRUE.

Я пробовал использовать SaveDC и RestoreDC до и после использования DirectX, теперь это привело к решению.

Использование wglSwapLayerBuffers вместо SwapBuffers не дает никаких изменений.

Могу я каким-то образом восстановить HWND или HDC в исходное состояние, или вы, ребята, знаете, почему это могло произойти?


person Sipka    schedule 31.05.2016    source источник


Ответы (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 по-прежнему не уничтожает должным образом модель переворота в окне, хотя я сделал все, что предлагалось в документации (вызовы ClearState и Flush).

CreateSwapChainForHwnd см. примечания

Изменить: через некоторое время я нашел этот вопрос. Если у кого-то еще есть идея, как снова вернуться к использованию GDI вместо резервного буфера DWM, мы будем очень признательны.

person Sipka    schedule 31.05.2016