Что нового в Direct3D 11.2

от автора

DirectX 11.2 вошедший в выпуск Windows 8.1 насчитывает ряд интересных и нужных нововведений. В этом посте будет проведен краткий обзор основных новинок, а так же рассмотрены некоторые сценарии применения. Несмотря на то что нововведений не так много, некоторые из них будут весьма кстати при разработке приложений для мобильных устройств, и приложений для Windows Store.

Кратко о новинках.

Основная часть работ которые были проделаны с DirectX 11.2 связана в первую очередь с производительностью и эффективности, и на прямую не коснется программистов. Ваши приложения будут быстрее работать и требовать меньше ресурсов. Тем не менее в Direct3D 11.2 API включено некоторое количество новых API:

  1. Поддержка аппаратных оверлеев: инструмент динамического масштабирования с интересными вариантами сценариев.
  2. Компиляция и линковка шейдеров HLSL в рантайме: возможность которая позволяет компоновать шейдеры во время выполнения, в том числе для приложений Windows Store.
  3. Отображаемые в память буфферы: Возможность которая позволяет убрать необходимость дополнительных операций копирования данных при обмене данными с GPU
  4. API снижения задержек ввода: Механизм который позволяет значительно снизить время задержки между пользовательским вводом и выводом результатов на экран.
  5. Тайловые ресурсы: Улучшение качества рендера с применением карт текстур.

Поддержка аппаратных оверлеев.

Одной из особенностей практически любого современного графического ускорителя является то что процедуры масштабирования графики являются очень дешевой операцией. В связи с этим возникает ряд сценариев которые интересно было бы использовать в случае если ощущается нехватка ресурсов или снижена скорость рендера.

Как уже понятно из картинки, аппаратный оверлей позволяет осуществлять рендер в буфер с низким разрешением, а затем увеличивать это изображение до необходимого размера и смешивать с дополнительными буферами через альфа-маску. Игра может отображать 3D сцену в первом оверлее с сниженным качеством, но при этом HUD или другие графические элементы приложения могут отображаться с высоким качеством.
При этом поддерживается два основных сценария применения аппаратных оверлеев — статический и динамический.

Статический оверлей.

Данный тип оверлея просто принимает уровень масштабирования при инициализации буфера и в дальнейшем не меняет своих значений. Для инициализации достаточно указать флаг DXGI_SCALING_STRETCH:

DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; swapChainDesc.Width = screenWidth / 1.5f; swapChainDesc.Height = screenHeight / 1.5f; swapChainDesc.Scaling = DXGI_SCALING_STRETCH;  ... dxgiFactory->CreateSwapChainForCoreWindow(     m_d3dDevice.Get(),     reinterpret_cast<IUnknown*>(m_window.Get()),     &swapChainDesc,     nullptr,     &swapChain     ); 

Применимость этого метода ограничивается случаями, в которых вы уже знаете уровень масштабирования заранее.

Динамический оверлей.

Более интересный вариант, в котором уровень масштабирования может меняться «на лету», без повторной инициализации буферов (Swapchain). Вам достаточно вызвать функцию SetSourceSize перед каждым рендером:

DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; swapChainDesc.Width = screenWidth; swapChainDesc.Height = screenHeight; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; dxgiFactory->CreateSwapChainForCoreWindow( ... ); ... if (fps_low == true) {     swapChain->SetSourceSize(screenWidth * 0.8f, screenHeight * 0.8f); } // рендер. ... swapChain->Present(1, 0); 

Динамический оверлей позволяет, в зависимости от текущей нагрузки на аппаратные ресурсы, моментально менять качество картинки без ущерба к FPS. Порой даже 10% снижение разрешения конечного изображения может в разы ускорить процедуры рендера, что положительно скажется на динамичных нагруженных сценах. У игроков пропадет ощущение «тормозов» в случаях когда на экран выводится слишком много объектов.

Компиляция и линковка шейдеров.

Динамическая компиляция шейдеров — это весьма удобный инструмент оптимизации во время работы приложения. К сожалению, в Windows 8.0, для приложений Windows Store эта возможность была недоступна, и разработчикам необходимо было создавать бинарные блобы шейдеров заранее. С выходом Windows 8.1 эта возможность вернулась и для приложений Windows Store.
В дополнение к этому появилась опция компиляции шейдеров ‘lib_5_0′ которая позволяет компоновать вычислительные блоки шейдеров и затем во время исполнения программы не компилировать шейдеры а только собирать из готовых библиотек. Эта возможность позволяет значительно повысить время подключения шейдера и исключить дорогую операцию компиляции во время исполнения приложения.

Отображаемые в память буферы.

В Windows 8.0 обмен данными с GPU для вычислительных шейдеров требует использования вспомогательных буфферов. Это налагает некоторые издержки, и как раз таки для вычислительных шейдеров может стоить дорого.

Если вы используете Windows 8.1 и DirectX 11.2 у вас есть возможность убрать две вспомогательные операции воспользовавшись флагом CPU_ACCESS. Тогда картинка будет выглядеть следующим образом:

Тем самым можно достичь увеличения производительности для вычислительных шейдеров. Следует отметить что пока эта возможность работает только для буферов данных, но не для текстур (Texture1D/2D/3D). Во всяком случае у разработчика есть простой путь проверки и работы напрямую или же с помощью вспомогательного буфера:

D3D11_FEATURE_DATA_D3D11_OPTIONS1 featureOptions; m_deviceResources->GetD3DDevice()->CheckFeatureSupport(     D3D11_FEATURE_D3D11_OPTIONS1,     &featureOptions,     sizeof(featureOptions)     ); ... If (featureOptions.MapDefaultBuffers) {     deviceContext->Map(defaultBuffer, ...); } else {     deviceContext->CopyResource(stagingBuffer, defaultBuffer);     deviceContext->Map(stagingBuffer, ...); } 

API снижения задержек ввода

Время между реакцией на ввод и реальным отображением результатов на экране является критичным для многих приложений, а особенно игр. Если это время слишком велико то у игрока появляется ощущение «тормозов» и дискомфорт. Оптимизация этого времени достаточно кропотливый процесс, но вместе с выходом DirectX 11.2 у программистов появился дополнительный механизм значительно облегчающий эту задачу. Появилось новое API IDXGISwapChain2::GetFrameLatencyWaitableObject которое позволяет получить WAIT HANDLE и в дальнейшем используя WaitForMultipleObjectEx дождаться самого удачного момента рендера:

DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; ... swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; dxgiFactory->CreateSwapChainForCoreWindow( ... ); HANDLE frameLatencyWaitableObject = swapChain->GetFrameLatencyWaitableObject(); while (m_windowVisible) {     WaitForSingleObjectEx(         frameLatencyWaitableObject,         INFINITE,         true         );     Render();     swapChain->Present(1, 0); } 

Например, результатом использования этого API может быть снижение времени задержки более чем вдвое на таких устройствах как Surface, с 46 миллисекунд до 20 миллисекунд.

Тайловые ресурсы


Современные игры требуют все большего и большего количества видео памяти, в том числе для текстур. От качества текстур и их разрешения напрямую зависит качество конечной картинки. Одним из методов оптимизации используемой видео памяти является механизм тайловых ресурсов Direct X 11.2 (Tiled resources). Чтобы понять о чем речь лучше посмотреть трехминутный ролик из пленарного доклада Build.

Ссылки и примеры

  1. Новое в C++/DirectX 11.2 разработке для Windows 8.1
  2. Тайловые ресурсы – доклад конфереции Build’13
  3. DirectX Foreground swapchain sample
  4. HLSL Shader Compiler sample
  5. DirectX latency sample
  6. Tiled resources sample

ссылка на оригинал статьи http://habrahabr.ru/post/199380/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *