Кратко о новинках.
Основная часть работ которые были проделаны с DirectX 11.2 связана в первую очередь с производительностью и эффективности, и на прямую не коснется программистов. Ваши приложения будут быстрее работать и требовать меньше ресурсов. Тем не менее в Direct3D 11.2 API включено некоторое количество новых API:
- Поддержка аппаратных оверлеев: инструмент динамического масштабирования с интересными вариантами сценариев.
- Компиляция и линковка шейдеров HLSL в рантайме: возможность которая позволяет компоновать шейдеры во время выполнения, в том числе для приложений Windows Store.
- Отображаемые в память буфферы: Возможность которая позволяет убрать необходимость дополнительных операций копирования данных при обмене данными с GPU
- API снижения задержек ввода: Механизм который позволяет значительно снизить время задержки между пользовательским вводом и выводом результатов на экран.
- Тайловые ресурсы: Улучшение качества рендера с применением карт текстур.
Поддержка аппаратных оверлеев.
Одной из особенностей практически любого современного графического ускорителя является то что процедуры масштабирования графики являются очень дешевой операцией. В связи с этим возникает ряд сценариев которые интересно было бы использовать в случае если ощущается нехватка ресурсов или снижена скорость рендера.
Как уже понятно из картинки, аппаратный оверлей позволяет осуществлять рендер в буфер с низким разрешением, а затем увеличивать это изображение до необходимого размера и смешивать с дополнительными буферами через альфа-маску. Игра может отображать 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.
Ссылки и примеры
ссылка на оригинал статьи http://habrahabr.ru/post/199380/
Добавить комментарий