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

в 14:09, , рубрики: DirectX, game development, Gamedev, windows, Windows 8.1, Блог компании Microsoft, метки: , ,

Что нового в 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. Тайловые ресурсы: Улучшение качества рендера с применением карт текстур.

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

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

Как уже понятно из картинки, аппаратный оверлей позволяет осуществлять рендер в буфер с низким разрешением, а затем увеличивать это изображение до необходимого размера и смешивать с дополнительными буферами через альфа-маску. Игра может отображать 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 для вычислительных шейдеров требует использования вспомогательных буфферов. Это налагает некоторые издержки, и как раз таки для вычислительных шейдеров может стоить дорого.
Что нового в Direct3D 11.2

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

Тем самым можно достичь увеличения производительности для вычислительных шейдеров. Следует отметить что пока эта возможность работает только для буферов данных, но не для текстур (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 миллисекунд.

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

Что нового в Direct3D 11.2
Современные игры требуют все большего и большего количества видео памяти, в том числе для текстур. От качества текстур и их разрешения напрямую зависит качество конечной картинки. Одним из методов оптимизации используемой видео памяти является механизм тайловых ресурсов 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

Автор: dmandreev

Источник

Поделиться

* - обязательные к заполнению поля